ผลิตภัณฑ์
แหล่งข้อมูลต่างๆ
ข้อมูลข่าวสารเฉพาะกลุ่ม
ข้อมูลเกี่ยวกับลิขสิทธิ์
สนใจซื้อ


 

การสร้าง Business Logic Layer

สารบัญ (Visual Basic)

  • คำนำ
  • ขั้นตอนที่ 1: การสร้างคลาส BLL
  • ขั้นตอนที่ 2: การเรียกใช้ Typed DataSets ผ่านทางคลาส BLL
  • ขั้นตอนที่ 3: การเพิ่มระบบตรวจสอบระดับฟิลด์ลงไปในคลาส DataRow
  • ขั้นตอนที่ 4: การเพิ่มกฎเกณฑ์ทางธุรกิจพิเศษให้แก่คลาส BLL
  • สรุป

คำนำ

การสร้าง Data Access Layer (DAL) ในแบบฝึกหัดที่ 1 เป็นการแยกตรรกะในการเรียกใช้ข้อมูลออกจากตรรกะในการแสดงผลข้อมูลอย่างเด็ดขาด  อย่างไรก็ตามแม้ว่า DAL สามารถแยกรายละเอียดการเรียกใช้ข้อมูลออกจากเลเยอร์นำเสนอข้อมูลได้ก็ตาม  แต่นั่นไม่ได้มีการบังคับใช้กฎเกณฑ์ทางธุรกิจใดๆตามไปด้วย  ตัวอย่างเช่น เราอาจต้องการให้แอพพลิเคชันของเราไม่ยอมให้มีการแก้ไขฟิลด์  CategoryID หรือ SupplierID ที่อยู่ในตาราง Products ถ้าหากฟิลด์  Discontinued  กำหนดให้เป็น  1  หรือเราอาจบังคับใช้กฎเกณฑ์ความอาวุโสโดยการห้ามไม่ให้พนักงานธรรมดามีสิทธิแก้ไขฟิลด์เหล่านี้ได้เป็นต้น   แนวทางพื้นฐานอีกแบบหนึ่งก็คือระบบตรวจสอบสิทธิ์  โดยอาจมีผู้ใช้ในบางแผนกเท่านั้นที่มีส่วนลบสินค้าหรือแก้ไขราคา UnitPrice ได้

ในแบบฝึกหัดนี้  เราจะดูว่าทำอย่างไรจึงจะนำเอากฎเกณฑ์ทางธุรกิจเหล่านี้ไปใส่ไว้รวมกันใน  Business  Logic Layer  (BLL) โดยที่ BLL ทำหน้าที่เป็นตัวกลางสำหรับการแลกเปลี่ยนข้อมูลระหว่างเลเยอร์แสดงผลข้อมูลกับ DAL ถ้าหากพูดถึงแอพพลิเคชันที่มีการใช้งานจริงแล้ว  เราควรนำเอา  BLL ไปใช้ในรูปของโครงการ Class Library แยกต่างหากมากกว่า   โดยในแบบฝึกหัดของเรา   เราจะใช้   BLL  ในรูปชุดของคลาสที่เก็บเอาไว้ในโฟลเดอร์ App_Code  เพื่อทำให้โครงสร้างของโครงการเรียบง่ายขึ้น ภาพที่ 1 แสดงความสัมพันธ์โครงสร้างระหวางเลเยอร์แสดงผล, BLL และ DAL

ภาพที่ 1: BLL แยกเลเยอร์แสดงผลออกจาก Data Access Layer และบังคับใช้กฎเกณฑ์ทางธุรกิจ

แทนที่จะต้องสร้างคลาสแยกจากกันสำหรับใช้โลจิกทางธุรกิจของเรา     แต่เราสามารถเลือกใช้วิธีใส่โลจิกลงไปใน Typed  dataSet  ได้โดยตรง โดยใช้ partial class ถ้าหากต้องการดูตัวอย่างวิธีการสร้างและขยายขอบเขตการใช้ Typed DataSet ให้คุณย้อนกลับไปดูแบบฝึกหัดแรกของเรา

ขั้นตอนที่ 1: การสร้างคลาส BLL

BLL  ของเราจะประกอบด้วยคลาส  4 อัน ซึ่งแต่ละอันใช้กับ TableAdapter แต่ละชุดที่อยู่ DLL นอกจากนั้นคลาส BLL เหล่านี้แต่ละอันจะมี method สำหรับการเรียก การเพิ่ม การอัพเดต และการลบจาก TableAdapter ที่เกี่ยวข้องใน DAL เพื่อประยุกต์ใช้กฎเกณฑ์ทางธุรกิจที่เหมาะสมต่อไปอีกด้วย

ถ้าหากต้องการแยกคลาสที่เกี่ยวข้องกับ  DAL  และ  BLL ให้เด็ดขาดยิ่งขึ้น ให้คุณสร้างโฟลเดอร์ย่อยสองอันในโฟลเดอร์  App_Code ที่ชื่อ DAL และ BLL ให้คุณคลิกเม้าส์ปุ่มขวาที่โฟลเดอร์ App_Code ใน Solution Explorer แล้วเลือกเมนู  New  Folder หลังจากสร้างโฟลเดอร์ทั้งสองขึ้นมาแล้ว ให้เข้าไปใน Typed DataSet ที่สร้างขึ้นมาในตัวอย่างแรก ซึ่งเก็บเอาไว้ในโฟลเดอร์ย่อย DAL

ขั้นต่อมาสร้างไฟล์คลาส  BLL  อีก  4 อันเอาไว้ในโฟลเดอร์ย่อย BLL วิธีการก็คือคลิกเม้าส์ปุ่มขวาที่โฟลเดอร์ย่อย BLL  เลือก  Add  a  New  Item  และเลือกเท็มเพล็ต  Class  ตั้งชื่อให้คลาสทั้ง 4 อันว่า ProductsBLL, CategoriesBLL, SupplierBLL และ EmployeesBLL

ภาพที่ 2: เพิ่มคลาสใหม่อีก 4 อันลงไปในโฟลเดอร์ App_Code

ขั้นต่อมาให้คุณเพิ่ม  method สำหรับคลาสแต่ละอัน เพื่อควบคุม method ที่กำหนดสำหรับ TableAdapter จากแบบฝึกหัดอันแรก  ในตอนนี้  method เหล่านี้จะถูกเรียกโดยตรงเข้าไปใน DAL ซึ่งเราจะย้อนกลับมาพูดเรื่องการเพิ่มโลจิกธุรกิจที่จำเป็นลงไปในภายหลัง

หมายเหตุถ้าหากคุณใช้  Visual Studio Standard Edition ขึ้นไป (นั่นหมายความว่าคุณไม่ได้ใช้ Visual Web Developer) คุณอาจใช้วิธีออกแบบคลาสแบวิชวลได้โดยใช้ Class Designe ก็ได้ ถ้าหากคุณต้องการทราบข้อมูลเกี่ยวกับคุณสมบัติใหม่ชนิดนี้ใน Visual Studio ให้เข้าไปดูใน Clas Designer Blog

เราต้องเพิ่ม mehods อื่นๆลงไปในคลาส ProductsBLL

  • GetProducts() -คืนค่าสินค้าทั้งหมดกลับไป
  • GetProductByProductID(productID) -คืนค่าสินค้าทั้งหมดซึ่งมีหมายเลขประจำตัวที่กำหนดกลับมา
  • GetProductsByCategoryID(categoryID) -คืนค่าสินค้าทั้งหมดตามหมวดหมู่ที่กำหนดกลับมา
  • AddProduct(productName,    supplierID,   categoryID,   quantityPerUnit,   unitPrice, unitsInStock,  unitsOnOrder,  reorderLevel,  discontinued) -ใส่รายการสินค้าใหม่ลงไปในดาต้าเบส โดยใช้ค่าต่างๆเหล่านี้ส่งผ่านเข้าไปแล้วคืนค่า ProductID ของเรกคอร์ดใหม่กลับมา
  • UpdateProduct(productName,   supplierID,   categoryID,  quantityPerUnit,  unitPrice, unitsInStock,  unitsOnOrder, reorderLevel, discontinued, productID) อัพเดตรายการสินค้าที่มีอยู่ในดาต้าเบสแล้ว  โดยใช้ค่าที่ส่งผ่านเข้าไป  จากนั้นคืนค่ากลับมาเป็น  True ถ้าหากมีการอัพเดตข้อมูลเพียงแถวเดียว แต่ถ้าเป็นกรณีอื่นให้สินค้ากลับมาเป็น False
  • DeleteProduct(productID) -ลบรายการสินค้าที่กำหนดจากดาต้าเบส

** code **

method  ที่คืนค่าข้อมูลกลับมา  (GetProducts,  GetProductByProductID, GetProductsByCategoryID และ  GetProductsBySuppliesID) จัดเป็น method ที่ทำงานตรงไปตรงมา โดยเพียงแต่เรียกไปยัง DAL เท่านั้น  แม้ว่าในบางสถานการณ์อาจจำเป็นต้องมีการใช้กฎเกณฑ์ทางธุรกิจในระดับนี้ก็ตาม  (อาทิเช่นกฎเกณฑ์การให้สิทธิโดยอิงกับผู้ใช้ที่ล็อกออนเข้ามา  หรือบทบาทของผู้ใช้เป็นต้น)เราจะปล่อยให้ method เหล่านี้เป็นแบบเดิมโดยไม่เข้าไปยุ่งเกี่ยวอะไร ซึ่งเมื่อพูดถึง methods เหล่านี้แล้ว BLL จะทำหน้าที่เป็นตัวกลางเท่านั้น โดยที่เลเยอร์แสดงผลจะเรียกใช้ข้อมูลจาก Data Access Layer

ระบบจะรับ  AddProduct  และ  UpdateProduct methods ในรูปของพารามิเตอร์ที่เก็บค่าของฟิลด์ต่างๆเกี่ยวกับสินค้า  เพื่อใช้เพิ่มรายการสินค้าใหม่  หรืออัพเดตสินค้าที่มีอยู่เดิมตามลำดับ  เนื่องจากคอลัมน์หลายคอลัมน์ที่อยู่ในตาราง Product สามารถรับค่า NULL ได้ (CategoryID, SupplierID และ UnitPrice รวมทั้งอื่นๆอีกมาก) ดังนั้นอินพุดพารามิเตอร์สำหรับ  AddProduct  และ UpdateProduct ที่โยงเข้าหาคอลัมน์เหล่านั้นจะกำหนดเป็นประเภทที่ใส่ค่า  NULL  ได้ การกำหนดประเภทที่ใส่ค่า NULL ได้จัดเป็นของใหม่ใน .NET 2.0 รวมทั้งยังเป็นเทคนิคที่ใช้กำหนดว่าประเภทของค่าควรจะเป็น   Nothing  มากกว่าหรือไม่  คุณสามารถอ่านข้อมูลเพิ่มเติมรวมทั้งเอกสารด้านเทคนิคของโครงสร้างที่กำหนดค่าเป็น  NULL  ได้ในหัวข้อ "ข้อเท็จจริงเกี่ยวกับประเภทที่กำหนดเป็น NULL ได้" ใน blog ของ Paul Vick

method  ทั้งสามอันส่งสินค้าบูลีนเพื่อระบุว่าต้องมีการเพิ่ม  อัพเดต หรือลบแถวหรือไม่ เนื่องจากการทำงานอาจไม่มีผลต่อแถวซึ่งได้รับผลกระทบ  ตัวอย่างเช่นถ้าหากนักพัฒนาเพจเรียก  DeleteProduct ให้ส่งค่า ProductID ของสินค้าที่ไม่มีอยู่เข้ามา   คำสั่ง   DELKETE  ที่ส่งไปยังดาต้าเบสจะไม่ได้รับผลกระทบ  จากนั้น  DeleteProduct method จะส่งค่ากลับมาเป็น False

หมายเหตุ เมื่อมีการเพิ่มรายการสินค้าใหม่ หรืออัพเดตรายการสินค้าที่มีอยู่เดิม เราจะได้รับค่าฟิลด์ใหม่ของสินค้าที่ได้รับการแก้ไขเข้ามา  ในรูปของรายการ scalars ซึ่งตรงข้ามกับการรับค่า ProductsRow เข้ามา เราเลือกใช้แนวทางนี้เนื่องจากคลาส  ProductsRow  มาจากคลาส  ADO.NET DataRow เป็น constructor ที่ไม่มีพารามิเตอร์ตั้งแต่แรก ถ้าต้องการสร้าง ProductsRow instance ขึ้นมาใหม่ เราต้องสร้าง ProductsDataTable ขึ้นมาก่อน  จากนั้นเรียก NewProductRow() method ขึ้นมา (ซึ่งเรามีอยู่แล้วใน AddProduct) จุดอ่อนดังกล่าวจะหายไปถ้าหากเราเปลี่ยนไปใช้วิธีการเพิ่มหรืออัพเดตสินค้าโดยใช้   ObjectDataSource   หรือกล่าวโดยสรุปก็คือ OubectDataSource  จะพยายามสร้าง  instance  สำหรับอินพุดพารามิเตอร์  ถ้าหาก BLL method ต้องการ ProductsRow  instance  แล้ว  ObjectDataSource  จะพยายามสร้างขึ้นมาให้ แต่จะทำไม่ได้เนื่องจากไม่มี parameterless   constructor   ตั้งแต่แรก  ถ้าหากต้องการทราบข้อมูลเพิ่มเติมเกี่ยวกับปัญหานี้ให้เข้าไปที่ข้อความสองข้อความที่โพสต์เอาไว้ในฟอร์ม  ASP.NET  ข้อความที่ว่าก็คือการอัพเดต  ObjectDataSources โดยใช้ DataSets  ที่กำหนดประเภทตายตัว  และปัญหาเกี่ยวกับ  ObjectDataSource และ DataSet ที่กำหนดประเภทตายตัว

ขั้นต่อมาใน AddProduct และ UpdateProduct โค้ดจะทำการสร้าง ProductsRow instance ขึ้นมาแล้วใส่ค่าที่ส่งผ่านมาลงไป   ถ้าหากมีการกำหนดค่าให้แก่  DataColumns  ของ  DataRow  ก็จะมีการตรวจสอบระดับฟิลด์หลายอย่างเกิดขึ้น ด้วยเหตุนี้การใส่ค่าด้วยมือที่ส่งผ่านมาลงไปใน DataRow จะช่วยให้คุณมั่นใจในความถูกต้องของข้อมูลที่ถูกส่งต่อไปยัง  BLL  method  โชคไม่ดีที่คลาส DataRow ที่กำหนดประเภทตายตัวซึ่งสร้างขึ้นมาโดย Visual Studio  ไม่อาจใช้ข้อมูลประเภทที่เป็น null ได้ ดังนั้นแทนที่จะระบุ Datacolumn อันใดอันหนึ่งใน DataRow ให้สอดคล้องกับดาต้าเบสที่เป็น NULL เราควรใช้ SetColumnNameNull() method จะดีกว่า

ใน  UpdateProduct  ก่อนอื่นเราต้องโหลดสินค้าขึ้นมาอัพเดตโดยใช้ GetProductByProductID(productID) แม้ว่าวิธีการนี้เหมือนกับการติดต่อกับดาต้าเบสที่ไม่จำเป็นก็ตาม  แต่การทำงานขั้นตอนนี้จะมีประโยชน์อย่างมากสำหรับแบบฝึกหัดอื่นๆในอนาคตที่จำเป็นต้องใช้เทคนิค  optimistic  concurrency  โดยที่เทคนิคนี้จะช่วยสร้างความมั่นใจว่าผู้ใช้สองคนที่กำลังทำงานกับข้อมูลชุดเดียวกันจะไม่เขียนข้อมูลทับการเปลี่ยนแปลงที่ผู้ใช้อีกคนหนึ่งกำลังทำอยู่ การดึงข้อมูลขึ้นมาทั้งเรกคอร์ดยังจะช่วยให้การสร้าง  method อัพเดตใน BLL ทำได้ง่ายขึ้น เนื่องจากเราจะแก้ไขเซ็ตย่อยของคอลัมน์  DataRow  เท่านั้น  ซึ่งตอนที่เราศึกษาเกี่ยวกับคลาส  SuppliersBLL เราจะพบตัวอย่างในลักษณะดังกล่าว

ท้ายสุด   มีการกำหนด   DataObject   attribute   ให้แก่คลาส  ProductsBLL  (ซินแทกซ์  [System.ComponentModel.DataObject]   ที่อยู่ก่อนคำสั่ง   class   ใกล้ด้านบนสุดของไฟล์)   และ   method  มี DataObjectMethodAttribute  attributes  ด้วย  โดยที่  DataObject attribute เป็นการกำหนดว่าคลาสนี้เป็นออปเจ็กต์ที่เหมาะกับการเชื่อมโยงไปยังคอนโทรล          ObjectDataSource          ในขณะที่ DataObjectMethodAttribute  เป็นการระบุจุดประสงค์ของ method นี้ สิ่งที่เราจะเห็นในแบบฝึกหัดชุดต่อๆไปก็คือ  ObjectdataSource  ของ  ASP.NET  2.0  จะช่วยให้การกำหนดการเรียกใช้ข้อมูลจากคลาสทำได้ง่ายขึ้น โดยปกติแล้วจะมีแต่คลาสซึ่งกำหนดให้เป็น   DataObjects  เท่านั้นจึงจะแสดงผลในรายการดรอปดาวน์ของวิซาร์ด เพื่อช่วยคัดกรองรายการคลาสที่เป็นไปได้สำหรับเชื่อมโยงไปยังวิซาร์ดของ    ObjectDataSource   แม้ว่าคลาส ProductsBLL  จะทำงานได้เป็นอย่างดีโดยที่ไม่มี attribute เหล่านี้ก็ตาม แต่การเพิ่ม attribute ลงไปจะช่วยให้ทำงานกับวิซาร์ดของ UbjectDataSource ทำได้ง่ายขึ้น

การเพิ่มคลาสอื่นๆ

หลังจากที่ทำคลาส   ProductsBLL   เสร็จแล้ว   เรายังจำเป็นต้องเพิ่มคลาสอื่นๆสำหรับทำงานกับหมวดหมู่สินค้า ซัพพลายเออร์ และพนักงานด้วย ให้คุณสร้างคลาสและ method เหล่านี้ขึ้นมาโดยใช้แนวทางจากตัวอย่างด้านบน

** code **

method  อันหนึ่งที่ควรจะพูดถึงก็คือ  UpdateSupplierAddress  method  ของคลาส  SuppliersBLL โดยที่ method นี้ได้เตรียมอินเทอร์เฟซสำหรับการแก้ไขเฉพาะที่อยู่ของซัพพลายเออร์เอาไว้ด้วย ซึ่งภายใน method นี้ จะทำการอ่านค่าของออปเจ็กต์       SupplierDataRow       เพื่อกำหนด      supplierID      (โดยใช้ GetSupplierBySupplierID)  รวมทั้งกำหนด properties ที่เกี่ยวข้องกับที่อยู่ จากนั้นเรียกกลับไปยัง Update method ของ SupplierDataTable โดยที่ UpdateSupplierAddress method จะมีหน้าตาแบบนี้

** code **

เขาไปดูในไฟล์ดาวน์โหลดของบทความนี้ เพื่อดาวน์โหลดคลาส BLL สมบูรณ์แบบของผมมาใช้

ขั้นตอนที่ 2: การเรียกใช้ Typed DataSets ผ่านทางคลาส BLL

ในแบบฝึกหัดอันแรก  เราเห็นตัวอย่างการทำงานโดยตรงกับ Typed DataSet มาแล้ว แต่เมื่อเพิ่มคลาส BLL ของเราลงไป  เลเยอร์ในการแสดงผลจะทำงานร่วมกับ  BLL  แทน ถ้าดูจากตัวอย่างไฟล์ AllProducts.aspx จากแบบฝึกหัดแรก  เราใช้  ProductsTableAdapter  เพื่อเชื่อมโยงรายการสินค้ากับ  GridView  เหมือนอย่างที่แสดงอยู่ในโค้ดด้านล่างนี้

** code **

ถ้าต้องการใช้คลาส  BLL  ใหม่นี้  สิ่งที่จำเป็นต้องมีการเปลี่ยนแปลงก็คือโค้ดบรรทัดแรก โดยคุณต้องเปลี่ยนจากออปเจ็กต์ ProductsTableAdapter ไปเป็นออปเจ็กต์ ProductBLL

** code **

นอกจากนั้นเรายังกำหนดการเรียกใช้คลาส    BLL    ได้    (เหมือนกับ    Typed    DataSet)   โดยใช้ ObjectDataSource เราจะศึกษา ObjectDataSource อย่างละเอียดในแบบฝึกหัดอันต่อๆไป

ภาพที่ 3: รายการสินค้าที่แสดงใน GridView

ขั้นตอนที่ 3: การเพิ่มระบบตรวจสอบความถูกต้องระดับฟิลด์ลงไปในคลาส DataRow

เราจะทำการตรวจเช็คการตรวจสอบความถูกต้องระดับฟิลด์ที่เกี่ยวข้องกับค่า property ของออปเจ็กต์เชิงธุรกิจก็ต่อเมื่อมีการเพิ่มหรือการอัพเดตข้อมูล กฎเกณฑ์การตรวจสอบความถูกต้องระดับฟิลด์สำหรับสินค้ามีดังนี้

  • ฟิลด์ ProductName ต้องมีความยาวน้อยกว่า 40 ตัวอักษร
  • ฟิลด์ QuantityPerUnit ต้องมีความยาวน้อยกว่า 20 ตัวอักษร
  • ฟิลด์ ProductID, ProductName และ Discontinued จำเป็นต้องใช้ ส่วนฟิลด์อื่นๆไม่จำเป็น
  • ฟิลด์ UniPrice, UnitsInStock, UnitsOnOrder และ RecordLevel จำเป็นต้องมากกว่าหรือเท่ากับศูนย์

กฎเกณฑ์เหล่านี้ควรกำหนดเอาไว้ในระดับดาต้าเบส  ข้อจำกัดเรื่องความยาวตัวอักษรของฟิลด์  ProductName และ QuantityPerUnit  อิงอยู่กับประเภทของข้อมูลตามคอลัมน์ต่างๆที่อยู่ในตาราง Products (nuarchar(40) และ nvarchar(20)   ตามลำดับ)   ฟิลด์เหล่านี้เป็นสิ่งที่จำเป็นหรือไม่ขึ้นอยู่กับว่าคอลัมน์ของตารางดาต้าเบสยอมรับค่า NULL  หรือไม่ โดยเรามีการตรวจเช็คข้อจำกัด 4 แบบเพื่อสร้างความมั่น่ใจว่ามีค่าที่สูงกว่าหรือเท่ากับศูนย์เท่านั้น ที่สามารถใส่ลงไปในคอลัมน์ UnitPrice, UnitsInStock, UnitsOnOrder หรือ ReorderLevel ได้

นอกเหนือจากการบังคับใช้กฎเกณฑ์ในระดับดาต้าเบสแล้ว  เราควรบังคับใช้กฎเกณฑ์ในระดับ  DataSet  อีกด้วย ที่จริงแล้วชุดของ  DataColumns  ของ DataTable แต่ละอันจะเป็นตัวกำหนดความยาวของฟิลด์ และจำเป็นต้องระบุค่าลงไปหรือไม่อยู่แล้ว   ถ้าหากต้องการดูว่ามีการเพิ่มระบบตรวจสอบความถูกต้องระดับฟิลด์ลงไปแล้วหรือไม่ให้เข้าไปใน   DataSet  Designer  เลือกฟิลด์จากตาราง  DataTables  อันใดอันหนึ่ง  จากนั้นก็เข้าไปในวินโดว์ส Properties    ซึ่งอย่างที่แสดงเอาไว้ในภาพที่    4    ก็คือ    QuantityPerUnit   Datacolumn   ใน ProductsDataTables มีความยาวสูงสุด 20 ตัวอักษรและยอมให้ใส่ค่า NULL ลงไปได้ ถ้าหากเราพยายามที่จะกำหนด  QuantityPerUnit  property  ของ  ProductsDataRow  ให้เป็นสตริงที่มีความยาวเกิน 20 ตัวอักษร ArgumentExceoption ก็จะเริ่มทำงาน

ภาพที่ 4: DataColumn มีระบบตรวจสอบความถูกต้องพื้นฐานระดับฟิลด์

โชคไม่ดีที่เราไม่สามารถกำหนดการตรวจเช็คแบบเชื่อมโยงได้  อาทิเช่นค่าของ UnitPrice จะต้องสูงกว่าหรือเท่ากับศูนย์ผ่านวินโดวส์  Properties  ถ้าหากต้องการใส่การตรวจสอบความถูกต้องระดับฟิลด์แบบนี้ลงไป  เราจำเป็นต้องสร้างตัวจัดการเหตุการณ์สำหรับ  ColumnChanging event ของ DataTable ขึ้นมา สิ่งที่เราเคยบอกเอาไว้ในแบบฝึกหัดก่อนหน้านี้ก็คือออปเจ็กต์  DataSet,  DataTables  และ  DataRow  ที่ถูกสร้างขึ้นมาโดย Typed DataSet  สามารถขยายขอบเขตการทำงานโดยใช้ partial classes การใช้เทคนิคนี้ช่วยให้เราสร้างตัวจัดการเหตุการณ์  ColumnChanging สำหรับคลาส ProductsDataTable ขึ้นมาได้ ให้เราเริ่มต้นโดยการสร้างคลาสในโฟลเดอร์ App_Code ที่ชื่อ ProductsDataTable.ColumnChanging.vb ขึ้นมา

ภาพที่ 5: การเพิ่มคลาสใหม่ลงไปในโฟลเดอร์ App_Code

ขั้นต่อมาสร้างตัวจัดการเหตุการณ์ของ   ColumnChanging  event  ที่รับประกันว่าค่าของคอลัมน์  UnitPrice, UnitsInStock,  UnitsOnOrder  และ  ReorderLevel (ถ้าไม่เป็น NULL) ต้องมากกว่าหรือเท่ากับศูนย์ ถ้าหากค่าของคอลัมน์ดังกล่าวอยู่นอกขอบเขตที่กำหนด ArgumentException ก็จะเริ่มทำงาน

** code **

ขั้นตอนที่ 4: การเพิ่มกฎเกณฑ์ทางธุรกิจพิเศษให้แก่คลาส BLL

นอกเหนือจากการตรวจสอบความถูกต้องระดับฟิลด์แล้ว     เรายังอาจต้องใส่กฎเกณฑ์ทางธุรกิจพิเศษระดับสูงที่เกี่ยวข้องกับองค์ประกอบหรือแนวคิดที่ไม่สามารถกำหนดในระดับคอลัมน์เดียวได้ อาทิเช่น

  • ถ้าหากสินค้าถูกยกเลิกการผลิต เราไม่สามารถอัพเดต UnitPrice ได้
  • ประเทศที่พนักงานอาศัยอยู่ ต้องเป็นประเทศเดียวกับที่อยู่ของผู้จัดการ
  • สินค้าไม่อาจยกเลิกการผลิตได้ ถ้าหากซัพพลายเออร์รายนี้มีสินค้าเพียงชนิดเดียว

คลาส  BLL  ควรมีระบบตรวจสอบเพื่อสร้างความมั่นใจว่าสอดคล้องกับกฎเกณฑ์ของธุรกิจของแอพพลิเคชัน การตรวจสอบดังกล่าวสามารถเพิ่มลงไปใน methods โดยตรงได้

สมมติว่ากฎเกณฑ์ทางธุรกิจของเรากำหนดว่า สินค้าชนิดหนึ่งไม่สามารถกำหนดสถานะว่ายกเลิกการผลิตได้ ถ้าหากเป็นสินค้าเพียงชนิดเดียวที่มาจากซัพพลายเออร์รายนี้  นั่นก็คือถ้าหากสินค้า  X  เป็นสินค้าเพียงชนิดเดียวที่เราซื้อมาจากซัพพลายเออร์  Y เราไม่สามารถกำหนดให้สินค้า X เป็นสินค้ายกเลิกการผลิตได้ อย่างไรก็ตามถ้าหากซัพพลายเออร์ ขายสินค้า A, B และ C ให้เรา เราสามารถกำหนดให้สินค้าชนิดใดชนิดหนึ่งหรือทั้งหมดเป็นสินค้ายกเลิกการผลิตได้ นี่เป็นกฎเกณฑ์ทางธุรกิจที่ค่อนข้างแปลกๆ แต่กฎเกณฑ์ทางธุรกิจและสามัญสำนึกมักไปด้วยกันไม่ด้วยได้

ถ้าหากต้องการบังคับใช้กฎเกณฑ์ทางธุรกิจเหล่านี้ใน  UpdateProducts method ให้เราเริ่มต้นโดยการตรวจเช็คดูว่ามีการกำหนด     Discontinued     เป็น     True    หรือไม่    ถ้าหากเป็นอย่างนั้น    ให้เราเรียก GetProductsBySupplierID เพื่อแยกแยะดูว่าเราซื้อสินค้าจากซัพพลายเออร์รายนี้มากน้อยเพียงใด ถ้าหากเราซื้อสินค้าเพียงชนิดเดียว AplicationException ก็จะเริ่มทำงาน

** code **

การรับมือกับความผิดพลาดจากการตรวจสอบความถูกต้องในหน้าจอแสดงผล

เมื่อเรียก BLL จากเลเยอร์แสดงผล เราสามารถตัดสินใจได้ว่าจะพยายามจัดการกับข้อยกเว้นใดๆ ที่อาจเกิดขึ้นหรือปล่อยให้ลอยไปอยู่กับ  ASP.NET ก็ได้ (ซึ่ง ASP.NET จะเรียก Error event ของ HttpApplication ขึ้นมา) ถ้าหากต้องการจัดการกับข้อยกเว้นเมื่อทำงานกับโปรแกรม  BLL เราสามารถใช้บล็อก Try... Catch ได้ เหมือนอย่างตัวอย่างต่อไปนี้

** code **

ในตัวอย่างต่อๆไปในอนาคต  เราจะเรียนรู้วิธีจัดการกับข้อยกเว้นที่มาจาก  BLL ตอนที่ใช้ดาต้าเว็บคอนโทรลสำหรับการเพิ่ม   การอัพเดต   หรือการลบข้อมูลให้สามารถจัดการโดยตรงในตัวจัดการเหตุการณ์  ซึ่งตรงกันข้ามกับวิธีใส่โค้ดลงไปในบล็อก Try.. Catch

สรุป

แอพพลิเคชันที่มีโครงสร้างที่ดีจะถูกแบ่งออกเป็นเลเยอร์ต่างๆซึ่งแยกออกจากกันโดยชัดเจน    โดยแต่ละเยอร์จะมีกฎเกณฑ์เฉพาะของตนบรรจุอยู่  แบบฝึกหัดอันแรกของเราเกี่ยวกับการสร้าง  Data  Access Layer โดยใช้ Typed DataSets  ส่วนในแบบฝึกหัดอันนี้เราสร้าง Business Logic Layer ในรูปชุดของคลาสที่เก็บเอาไว้ในโฟลเดอร์ App_Code  ของแอพพลิเคชัน จากนั้นคลาสสามารถเรียกเข้าไปใน DAL ได้ BLL เป็นการใช้โลจิกระดับฟิลด์และระดับธุรกิจภายในแอพพลเคชันของเรา  ซึ่งนอกเหนือจากการสร้าง  BLL  แยกต่างหาก (เหมือนอย่างที่เราทำให้ดูในแบบฝึกหัดนี้ ทางเลือกอีกแบบหนึ่งก็คือการขยายขอบเขต  method  ต่างๆของ  TableAdapter ผ่านทางการใช้ partial  class อย่างไรก็ตามการใช้เทคนิคนี้ไม่ยอมให้มีการเขียนทับ method ที่มีอยู่แล้ว และไม่ยอมให้เราแยก DAL ออกจาก BLL อย่างชัดเจน เหมือนอย่างแนวทางที่เราใช้ในบทความนี้

หลังจากสร้าง  DAL และ BLL เสร็จแล้ว เราก็พร้อมที่จะสร้างเลเยอร์แสดงผลเป็นอันดับต่อไป โดยในแบบฝึกหัดอันต่อไป  เราจะเลิกยุ่งกับการเรียกใช้ข้อมูลชั่วขณะ จากนั้นเราจะเรียนรู้วิธีกำหนดเพจเลเยอร์เอาท์ให้สอดคล้องกันทั่วทั้งแบบฝึกหัดชุดนี้

 


Microsoft