จัดการข้อมูลบน Silverlight 2 เบต้า 2 ด้วย WCF และ LINQ to SQL


 

จากบทความที่ผมเขียนตีพิมพ์ลง นิตยสาร CODE IT [สอดอยู่ในเล่ม Windows ITPro ฉบับเดือน ตุลาคม 2551] ซึ่งผมได้ขออนุญาตในการนำบทความไปเผยแพร่จากทางสำนักพิมพ์เป็นที่เรียบร้อยแล้ว ติดตามกันได้เลยครับ:

 

Download source:
http://cid-7d608959d854cb28.skydrive.live.com/embedrowdetail.aspx?path=/CODEITMAGAZIN/CRUD|_SL2b2|_WCF|_LINQ|_%u0e08%u0e31%u0e14%u0e01%u0e32%u0e23%u0e02%u0e49%u0e2d%u0e21%u0e39%u0e25%u0e1a%u0e19Silverlight2beta2%u0e14%u0e49%u0e27%u0e22WCF%u0e41%u0e25%u0e30LINQ.zip

 

สวัสดีครับ กลับมาพบกันเช่นเคย คราวนี้ผมมีโค้ดสนุกๆ มาเล่าสู่กันฟังเช่นเดิม โทคโนโลยีทุกวันนี้มีการพัฒนาไปอย่างรวดเร็ว จนแม้เราๆ ท่านๆ ฐานะผู้ใช้งาน รู้สึกว่ามิได้มีเวลาเพียงพอสำหรับการเรียนรู้ และก้าวตามให้ทัน แม้สรรพสิ่งบนโลกใบนี้ล้วนมีเวลาเท่าเทียมกัน คือ 24 ชั่วโมงก็ตามที แต่ก็นั่นแล… อยู่ที่ว่าใครจะจัดสรรเวลาให้กับช่วงจังหวะชีวิตได้ดีกว่า และบางช่วงเวลาดังกล่าว เก็บไว้สำหรับซึมซับช่วงเวลาที่กำลังจะผ่านไป… วันเวลายิ่งผ่านไปเทคโนโลยียิ่งเปลี่ยนแปลง เปลี่ยนแปลงสู่สิ่งที่ดีกว่า เฉกเช่นเมื่อวันที่ 6 มิถุนายน 2551 ไมโครซอฟท์ได้เปิดตัว Silverlight 2 เบต้า 2 โดยสิ่งที่เปลี่ยนแปลงสำคัญเช่น เพิ่มคอนโทรลเข้ามาอีกกว่า 30 แบบจาก เบต้า1 ซึ่งเป้าหมายของ Silverlight 2.0 ตัวจริงคือ คอนโทรลที่มากกว่า 100 คอนโทรล และแอพพลิเคชันที่พัฒนาบน Silverlight 1.0 สามารถนำใช้งานบน Silverlight 2.0 เบต้า 2 ได้อย่างไม่มีปัญหา และไมโครซอฟท์กล่าวว่าจะมีการเปลี่ยน API อีกพอสมควรกว่า Silverlight 2.0 ตัวที่จริงจะออกในเร็วๆ นี้ ซึ่งทำให้เราสามารถพัฒนาแอพพลิเคชันด้วย Silverlight 2 บน VS2008 และ Expression Blend 2.5 June 2008 Preview ได้ลงตัวมากขึ้นเรียกได้ว่าหากท่านใดเคยใช้งานเครื่องมือของไมโครซอฟท์อยู่แล้วแทบไม่จำเป็นต้องศึกษาเรื่องใหม่ และเมื่อเราทำการติดตั้งเครื่องมือ Microsoft Silverlight Tools Beta 2 for Visual Studio 2008 จะทำให้เราได้รับการติดตั้งแพคเกจ Silverlight 2 เบต้า 2 รันไทม์ และ Silverlight 2 เบต้า 2 SDK พร้อมให้เลือกสรรในการพัฒนาแอพพลิเคชัน และที่สำคัญใน Silverlight 2 เบต้า 2 ยังสนับสนุนใบอนุญาตแบบ go-live ซึ่งทำให้เราสามารถเริ่มวางแผน และเริ่มโครงการในเชิงพาณิชย์ได้ทันที โดยไมโครซอฟท์ยังกล่าวว่าจะมีการเปลี่ยนแปลง API บางตัวระหว่าง เบต้า 2 และรุ่นสุดท้าย ดังนั้นเราอาจจะต้องปรับปรุงโปรแกรมประยุกต์ที่เราเขียน เมื่อมีการเผยแพร่รุ่นสุดท้ายออกมา บ้างเล็กน้อย

และต่อมาเมื่อวันจันทร์ที่ 11 สิงหาคม 2551 ที่ผ่านมา ไมโครซอฟท์ได้ปล่อย Service Pack 1 (SP1) สำหรับ Visual Studio 2008 ออกมา เป็นการรวมเอาอัพเดตสำคัญๆ หลายๆ ตัวที่ปล่อยออกมาในช่วงที่ผ่านมาไว้ด้วยกัน รวมถึงฟีเจอร์ใหม่ๆ ของ WPF เช่น Client Deployment Pack สำหรับ .Net Framework และสำหรับฝั่ง Silverlight 2 ก็ได้ออก Tools สำหรับ Visual Studio 2008 SP1 ตามมาติดๆ ในวันเดียวกัน เรียกได้ว่าเทคโนโลยีทุกวันนี้มีการพัฒนาอย่างไม่หยุดยั้ง ทำให้ผู้ใช้อย่างเราๆ ท่านๆ ต้องก้าวตามให้ทัน กันต่อไป

สำหรับในบทความนี้ขอนำเสนอโค้ดสนุกๆ และฟีเจอร์ใหม่ๆ ที่มีมาใน Silverlight 2 เบต้า 2 (ขณะกำลังร่างต้นฉบับเป็นเวอร์ชัน Silverlight 2 เบต้า 2 บน Visual Studio 2008 SP1) ขอนำท่านผู้อ่านเข้าสู่การจัดการกับข้อมูลบน Silverlight 2 เบต้า 2 ด้วย WCF และ LINQ to SQL ซึ่งเราจะไปทดลองใช้ฟีเจอร์ใหม่ที่มาใน Silverlight 2 เบต้า 2 นั่นคือตัว DataGrid คอนโทรล และ WCF ในชื่อ Silverlight-enabled WCF Service และใช้ LINQ to SQL ในการจัดการกับข้อมูล (เพิ่ม-แก้ไข-ลบ) และการกำหนดฟอนต์ (font) ภาษาไทยบน Silverlight 2 เบต้า 2 ให้แอพพลิเคชันของเราสามารถทำงานกับภาษาไทยได้ โดยหน้าจอแอพพลิเคชันของเราเป็นดังรูปที่ 1

 

1

รูปที่ 1 หน้าจอระบบจัดการข้อมูลบน Silverlight 2 beta 2 ด้วย WCF และ LINQ

 

สิ่งที่จำเป็นสำหรับบทความ:

 

 

ขั้นตอนการพัฒนาแอพพลิเคชัน:

ในบนความนี้เป็นการกล่าวถึงการจัดการข้อมูลบน Silverlight 2 เบต้า 2 ด้วย WCF และ LINQ to SQL ดังที่ได้กล่าวไปแล้วในขั้นต้น โดยการใช้งานเครื่องมือ Expression Blend และ VS2008 ร่วมประสานในการพัฒนาแอพพลิเคชัน กล่าวคือ เครื่องมือ Expression Blend ใช้สำหรับออกแบบหน้าตาแอพพลิเคชัน และเครื่องมือ VS2008 ใช้สำหรับใส่โค้ดให้หน้าตาแอพพลิเคชันดังกล่าวปฏิบัติการสิ่งใดๆ ตามเป้าประสงค์ของเรา และด้วยเหตุว่า Silverlight 2 ยังเป็นเวอร์ชันเบต้าอยู่ ฉะนั้นย่อมไม่ต้องใจเหล่านักพัฒนาทุกเรื่องไป เฉกเช่นเรื่องการใช้งานฟอนต์ โดยเฉพาะกับภาษาไทยด้วยแล้วยังไม่มีให้เลือกใช้งาน แต่ใช่ว่าเราจะหมดหนทางไม่ เราสามารถนำฟอนต์ที่มีในระบบ (OS) ไปใช้งานได้ตามใจต้องการ ซึ่งวิธีการต่างๆ จะกล่าวถึงในไม่ช้านี้ และขอแบ่งขั้นตอนการพัฒนาแอพพลิเคชันออกเป็นขั้นตอนต่างๆ ดังต่อไปนี้

  • ขั้นตอนที่ หนึ่ง: สร้างโปรเจ็กต์ Silverlight 2
  • ขั้นตอนที่ สอง: กำหนดฟอนต์ใน Silverlight 2
  • ขั้นตอนที่ สาม: เพิ่ม DataGrid คอนโทรลด้วยเครื่องมือ Expression Blend
  • ขั้นตอนที่ สี่: ออกแบบหน้าแอพพลิเคชันด้วยเครื่องมือ Expression Blend
  • ขั้นตอนที่ ห้า: เพิ่ม Silverlight-enabled WCF Service และ LINQ to SQL
  • ขั้นตอนที่ หก: ใส่โค้ดในฝั่งเซอร์ฟเวอร์ และฝั่งไคลเอ็นต์
  • ขั้นตอนที่ เจ็ด: ทดสอบแอพพลิเคชัน

ขั้นตอนที่ หนึ่ง: สร้างโปรเจ็กต์ Silverlight 2

ให้เราหยิบเครื่องมือมีระดับอย่าง VS2008 ขึ้นมาแล้วดำเนินการสร้างโปรเจ็กต์ใหม่ ด้วยเทมเพลต Silverlight Application บทความนี้ขอตั้งชื่อโซลูชันเป็น CRUD_SL2b2_WCF_LINQ เราจะได้โปรเจ็กต์ประกอบด้วยสองโปรเจ็กต์ดังรูปที่ 2

 

2

รูปที่ 2 สร้างโปรเจ็กต์ Silverlight 2

จากรูปที่ 2:

หากท่านผู้อ่านได้ติดตามบทความสร้างแอพพลิเคชันง่ายๆ ด้วย Silverlight 2 RIA, WCF และ LINQ ใน นิตยสาร CODEIT ฉบับพฤษภาคม – มิถุนายน 2551 ที่สอดภายในนิตยสาร WindowsITPro ฉบับประจำเดือน พฤษภาคม 2551 ได้กล่าวไปแล้วว่า โปรเจ็กต์ที่เป็น ASP.Net จะทำงานในฝั่ง Server และโปรเจ็กต์ Silverlight จะทำงานฝั่งไคลเอ็นต์

เมื่อเราได้โซลูชันที่ประกอบด้วยโปรเจ็กต์สองโปรเจ็กต์ดังกล่าวคือ โปรเจ็กต์ ASP.Net และ โปรเจ็กต์ Silverlight ในขั้นตอนลำดับต่อไปเราจะไปกำหนดฟอนต์ให้โปรเจ็กต์ Silverlight ของเราให้สามารถแสดงภาษาไทย เนื่องจากเราจะใช้แสดงข้อมูลที่เป็นภาษาไทยดังกล่าวด้วยครับ

 

ขั้นตอนที่ สอง: กำหนดฟอนต์ใน Silverlight 2

จากขั้นตอนที่หนึ่งเราได้สร้างโปรเจ็กต์บน VS2008 เรียบร้อยแล้วตอนนี้เรากำลังทำงานอยู่บนเครื่องมือ VS2008 และเนื่องจากว่าใน Silverlight 2 เบต้า 2 ยังไม่มีฟอนต์ภาษาไทยให้เราเลือกใช้งาน เราต้องไปยืมฟอนต์ในระบบมาใช้งานก่อน ซึ่งมีขั้นตอนดังนี้:

  • เข้าไปยืมฟอนต์ระบบในพาธ C:WINDOWSFonts แล้วทำการ copy ฟอนต์ที่ต้องการออกมาวางข้างนอกพาธ C:WINDOWSFonts เช่นวางไว้บนเดสก์ทอป เพื่อให้เราสามารถมองเห็นจากเครื่องมือ VS2008
  • เพิ่มฟอนต์ดังกล่าวเข้าไปในโปรเจ็กต์ Silverlight ทำได้โดยการลากไปวางบนโปรเจ็กต์ Silverlight บนเครื่องมือ VS2008
  • ปรับพรอเพอร์ตี้ของฟอนต์ Build Action เป็น Resource จากนั้น Build หนึ่งครั้ง เพื่อเป็นการฝัง (Embed) ฟอนต์ดังกล่าวเข้าไปใน Resource ของโปรเจ็กต์ Silvertlight
  • ให้เราสลับเครื่องมือไปที่เครื่องมือ Expression Blend โดยคลิกขวาบนโปรเจ็กต์ Silverlight แล้วเลือกเมนู Open in Expression Blend… จากนั้นไปที่แท็บ Properties ตรงช่อง Search พิมพ์คำว่า font จะมีกล่องเครื่องมือ Text แสดงออกมา แล้วทำการเลือกฟอนต์เราจะพบว่ามีฟอนต์ที่เราได้ทำการเพิ่มไปเมื่อครู่ให้เราเลือกใช้งานได้แล้วดังรูปที่ 3

 

3

รูปที่ 3 กำหนดฟอนต์ในโปรเจ็กต์ Silverlight 2

จากขั้นตอนที่สองเราได้สลับเครื่องมือไปทำงานบนเครื่องมือ Expression Blend ในขั้นตอนต่อไปเราไปทำการเพิ่มคอนโทรล DataGrid ด้วยเครื่องมือ Expression Blend กันครับ

 

ขั้นตอนที่ สาม: เพิ่ม DataGrid คอนโทรลด้วยเครื่องมือ Expression Blend

การเพิ่มคอนโทรล DataGrid ด้วย Expression Blend สามารถกระทำได้ดังนี้:

  • เพิ่ม References System.Windows.Controls.Data.dll (C:Program FilesMicrosoft SDKsSilverlightv2.0LibrariesClientSystem.Windows.Controls.Data.dll) เข้ามาในโปรเจ็กต์ Silverlight เพื่อเราสามารถใช้งานกลุ่ม Data Control
  • คลิกบน Asset Library บนกล่องเครื่องมือด้านขวา เราจะได้หน้าต่าง Asset Library ให้คลิกที่แทบ Custom Controls เราจะเห็น คอนโทรล DataGrid ดังรูปที่ 4 ให้ทำการดับเบิ้ลคลิกบน คอนโทรล DataGrid ดังกล่าว เพิ่มเข้ามาในอาร์ตบอร์ด (Page.xaml)

 

4

รูปที่ 4 เพิ่ม DataGrid คอนโทรลด้วยเครื่องมือ Expression Blend

เมื่อเราทำการเพิ่ม คอนโทรล DataGrid เป็นที่เรียบร้อยแล้วขั้นตอนต่อไปเราจะไปทำการเพิ่มคอนโทรลอื่นๆ ที่เหลือ และทำการออกแบบหน้าตาแอพพลิเคชันด้วยเครื่องมือ Expression Blend

 

ขั้นตอนที่ สี่: ออกแบบหน้าแอพพลิเคชันด้วยเครื่องมือ Expression Blend

ในขั้นตอนนี้เรามาทำการออกแบบหน้าตาแอพพลิเคชันดังรูปที่ 5

 

5

รูปที่ 5 ออกแบบหน้าแอพพลิเคชันด้วยเครื่องมือ Expression Blend

จากรูปที่ 5:

  • หมายเลข 1 คือหน้าตาแอพพลิเคชันเป้าประสงค์ของเรา
  • หมายเลข 2 ส่วนประกอบของคอนโทรลต่างๆ ที่ใช้งานดังนี้
    • ให้เราทำการแบ่ง LayoutRoot (Grid) เป็นสี่แถว โดยวิธีการแบ่งเพียงนำเมาส์ไปชี้ตรงขอบของ LayoutRoot จะมีเส้นสีส้มเกิดขึ้น ให้เราคลิกเมาส์ลงไปเราจะได้แถวตามต้องการ จากนั้นเส้นสีส้มจะกลายเป็นเส้นสีน้ำเงิน จากนั้นเราจึงนำคอนโทรลต่างๆ ไปวางในแต่ละแถว
    • แถวแรกใส่ TextBlock แสดงป้ายชื่อแอพพลิเคชัน
    • แถวที่สองใส่คอนโทรลป้ายชื่อและช่องป้อนข้อมูล และปุ่มกด (Button) โดยคอนโทรล TextBlock ใช้แสดงป้ายชื่อ และ TextBox ใช้สำหรับเป็นช่องใส่ข้อมูล และเอาทั้งสองคอนโทรลไปใส่ในตัวบรรจุ ประเภท StackPanel เพื่อให้จัดคอนโทรล TextBlock และ คอนโทรลTextBox ให้ซ้อนกันตามแนวนอน จะเห็นว่าเรามีคอนโทรล TextBlock และ คอนโทรลTextBox สามชุด นั่นแสดงว่าเราต้องใช้ตัวบรรจุประเภท StackPanel จำนวนสามคอนโทรลเช่นกัน และคอนโทรล StackPanel อีกตัวหนึ่งสำหรับบรรจุปุ่มกดโดยให้ซ้อนกันตามแนวตั้ง สำหรับการจัด Layout บน Silverligh 2 ศึกษาเพิ่มได้จาก Object Positioning and Layout (Silverlight 2): http://msdn.microsoft.com/en-us/library/cc189087(VS.95).aspx
    • แถวที่สามใส่ป้ายชื่อแสดงสถานะการทำงาน
    • แถวสุดท้ายใส่คอนโทรล DataGrid เพื่อบรรจุข้อมูล

การออกแบบหน้าตาแอพพลิเคชันเป็นอันเรียบร้อย ขั้นตอนต่อไปเราต้องสลับการใช้เครื่องมือไปใช้งานเครื่องมือ VS2008 เพื่อไปทำการเพิ่ม WCF Service และ LINQ to SQL

 

ขั้นตอนที่ ห้า: เพิ่ม Silverlight-enabled WCF Service และ LINQ to SQL

ใน Silverlight 2 เบต้า1 เมื่อเราสร้าง WCF Service เราจะใช้ WCF Service template ใน VS2008 ซึ่งในการ binding แล้ว เราจะต้องเข้าไปปรับเปลี่ยนไฟล์ config ใน ASP.NET web.config จาก wsHttpBinding ไปเป็น basicHttpBinding เนื่องจาก Silverlight Support การ binding แบบ basicHttpBinding นั่นเอง

แต่สำหรับใน Silverlight 2 เบต้า 2 หลังจากที่เราทำการติดตั้ง tools เครื่องมือสำหรับ VS2008 แล้วเราจะได้ item ชนิดใหม่ขึ้นมา ชื่อ Silverlight-enabled WCF Service ดังรูปที่ 6 สำหรับ Silverlight-enabled WCF Service นั้น ส่วน interface และ implementation ถูกรวมเป็นเพียงหนึ่งคลาส เพื่อช่วยให้การใส่โค้ดนั้นง่ายขึ้น

 

6

รูปที่ 6 เพิ่ม Silverlight-enabled WCF Service

เมื่อเราทำการเพิ่ม WCF Service เรียบร้อยแล้ว ต่อไปเราไปเพิ่ม LINQ ดังรูปที่ 7 หมายเลข 1 ให้เราเพิ่มเทมเพลต lINQ to SQL Class เข้ามาในโปรเจ็กต์ ASP.Net จากนั้นทำการสร้างคอนเนคชันชี้ไปที่ฐานข้อมูล Northwin ในบทความนี้จะกล่าวถึงการจัดการข้อมูลเฉพาะตาราง Category ให้ทำการลากตาราง Category มาวางบนพื้นที่ออกแบบ (Design surface) และปรับพรอเพอร์ตี้ Serailization Mode เป็น unidirectional ดังรูปที่ 7 หมายเลข 1

 

7

รูปที่ 7 เพิ่ม LINQ to SQL

ขั้นตอนที่ห้า เพิ่ม Silverlight-enabled WCF Service และ LINQ to SQL เป็นอันเสร็จเรียบร้อย ขั้นต่อไปรเจะไปทำการใส่โค้ดให้หน้าจอแอพพลิเคชันปฏิบัติการตามที่เราต้องการ นั่นคือการจัดการข้อมูล เพิ่ม – แก้ไข – ลบข้อมูล

 

ขั้นตอนที่ หก: ใส่โค้ดในฝั่งเซอร์ฟเวอร์ และฝั่งไคลเอ็นต์

มาถึงขั้นตอนที่หกนี้ เรายังอยู่ที่เครื่องมือ VS2008 เราจะไปทำการโค้ดดิ้งให้แอพพลิเคชัน จัดการข้อมูลบนตาราง Category กันครับ การใส่โค้ดแบ่งเป็นสองส่วน กล่าวคือ ใส่โค้ดในฝั่งเซอร์ฟเวอร์ และฝั่งไคลเอ็นต์ โดยในฝั่งเซอร์ฟเวอร์ เป็นส่วนให้บริการดัง ลิสต์ติ้งที่ 1 และโค้ดฝั่งไคลเอ็นต์จะเป็นผู้ใช้บริการดัง ลิสต์ติ้งที่ 2

เมื่อทำการใส่โค้ดเป็นที่เรียบร้อยแล้ว ขั้นตอนสุดท้ายของการพัฒนาแอพพลิเคชัน เราไปทำการทดสอบดูผลว่า ระบบจะปฏิบัติตามที่เราสั่งมากน้อยเพียงใด

 

ขั้นตอนที่ เจ็ด: ทดสอบแอพพลิเคชัน

เราไปทำการทดสอบดูซิว่าระบบสามารถจัดการข้อมูลตามเป้าประสงค์ของเราหรือไม่ เราทดสอบด้วยกันสามส่วนได้แก่ ส่วนแรกเป็นการเพิ่มข้อมูล, ส่วนที่สองเป็นการแก้ไขข้อมูล และส่วนสุดท้ายเป็นการลบข้อมูล

การเพิ่มข้อมูล:

  • หมายเลข 1 คลิกปุ่ม New เป็นการเพิ่มข้อมูลใหม่
  • หมายเลข 2 ให้ทำการป้อนข้อมูล CategoryName และ Desceription จากนั้นกดปุ่ม Save
  • หมายเลข 3 มีหน้าต่างแสดงการทำการเพิ่มข้อมูล
  • หมายเลข 4 ทำการโหลดข้อมูลใส่ DataGrid ทันที

 

8

รูปที่ 8 หน้าจอเพิ่มข้อมูล

การแก้ไขข้อมูล:

  • หมายเลข 1 คลิกข้อมูลที่ต้องการแก้ไขบนแถวของ DataGrid ข้อมูลดังกล่าวจะถูกโหลดใส่ TextBox
  • หมายเลข 2 ให้ทำการคลิกปุ่ม Edit จากนั้นทำการเปลี่ยนแปลงข้อมูล และกดปุ่ม Save เพื่อบันทึกข้อมูล จะมีหน้าต่างแสดงการแก้ไขข้อมูล

 

9

รูปที่ 9 หน้าจอแก้ไขข้อมูล

การลบข้อมูล:

  • หมายเลข 1 คลิกข้อมูลที่ต้องการลบบนแถวของ DataGrid ข้อมูลดังกล่าวจะถูกโหลดใส่ TextBox
  • หมายเลข 2 ให้ทำการคลิกปุ่ม Delete จากนั้นจะมีหน้าต่างยืนยันการลบข้อมูล เมื่อเราตอบ OK เพื่อยืนยันการลบ ข้อมูลบน DataGrid แถวดังกล่าวจะหายไป และมีหน้าต่างแสดงผลการลบข้อมูล

 

10

รูปที่ 10 หน้าจอลบข้อมูล

Silverlight 2 เบต้า 2 สามารถจัดการกับข้อมูลได้อย่างง่ายๆ ไม่ใช่เรื่องยากอีกต่อไป แม้เทคโนโลยีจะก้าวหน้ารวดเร็วเพียงใด เรา และท่านผู้อ่านในฐานะนักพัฒนา, ในฐานะผู้สร้างความก้าวหน้าให้องค์กร, ผู้สร้างความก้าวหน้าให้บ้านเมือง ให้ประเทศชาติ แม้จะก้าวตามทันบ้าง ไม่ทันบ้าง แต่อย่างน้อยให้เรารับรู้ว่า แท้จริงแล้วเส้นทางที่เราจะเดินต่อในก้าวต่อไป คือเส้นทางใด?… และแม้ว่าสังคมจะมีการแข่งขันสูง ชีวิตมีแต่ความเร่งรีบ จนบางครั้งรู้สีกว่าไม่มีเวลาเพียงพอสำหรับบางจังหวะของชีวิต แม้แท้จริงแล้วโลกใบนี้มิได้หมุนเร็วขึ้นแต่ประการใด ขอให้ประสบโชคดี มีแต่ความสุขกันทุกๆ ท่านครับ

แล้วพบกันบนชุมชนออนไลน์ http://www.greatfriends.biz เพื่อแลกเปลี่ยนประสบการณ์ สาระ ความรู้ กันและกัน และไปเยี่ยมกล่าวคำทักทายกันได้บน Blog ส่วนตัว: กรรมกรซอฟต์แวร์ http://janawat.spaces.live.com

 

ลิสต์ติ้งที่ 1: โค้ดในฝั่งเซอร์ฟเวอร์

Service.cs

using System;

using System.Linq;

using System.Runtime.Serialization;

using System.ServiceModel;

using System.ServiceModel.Activation;

using System.Collections.Generic;

[ServiceContract(Namespace = "")]

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]

public class Service

{

/// <summary>

/// เมธอด GetCategoryAll

/// ดึงข้อมูลในออบเจ็กต์ Categories (ตาราง Category)

/// </summary>

/// <returns>

/// ส่งข้อมูล ออบเจ็กต์ Categories แบบ List

/// </returns>

[OperationContract]

public List<Category> GetCategoryAll()

{

using (DataClassesDataContext db = new DataClassesDataContext())

{

return db.Categories.ToList();

}

}

/// <summary>

/// เมธอด updateCategory(Category category)

/// อับเดตข้อมูลอ็อบเจ็กต์ Categories

/// </summary>

/// <param name="category"></param>

/// <returns>

/// ส่งข้อความกลับให้ไคลน์เอ็นต์ เมื่ออับเดตข้อมูลเรียบร้อยแล้ว

/// </returns>

[OperationContract]

public string updateCategory(Category category)

{

string resualt = "";//ตัวแปรเก็บข้อความ เพื่อส่งให้ไคลเอ็นต์เมื่อทำงานแล้ว

try

{

using (DataClassesDataContext db = new DataClassesDataContext())

{

//ดึงข้อมูล Category ตาม CategoryID ที่ไคลเอ็นต์ส่งมา เพื่อนำมาอับเดต

var oc = (from c in db.Categories

where c.CategoryID == category.CategoryID

select c).First();

//ถ่ายค่า category ใหม่ที่ไคลเอ็นต์ส่งมาให้อ็อบเจ็ก oc ที่เราดึงได้

oc.CategoryName = category.CategoryName;

oc.Description = category.Description;

oc.Picture = category.Picture;

//บันทึกกลับอ็อบเจ็กต์ oc กลับไปที่ตารางจริง

db.SubmitChanges();

//เก็บข้อความแสดงให้ไคลเอ็นต์รู้ว่าแก้ไขข้อมูลเรียบร้อย

resualt = "Update Category completed…";

}

}

catch (System.Exception e)

{

//เก็บข้อความเมื่อเกิดข้อผิดพลาด

resualt = "Update Category Error…" + e.Message;

}

//ส่งข้อความแสดงการทำงานกลับให้ไคลเอ็นต์

return resualt;

}

/// <summary>

/// เมธอด insertCategory(Category category)

/// เพิ่มข้อมูล Categories

/// </summary>

/// <param name="category"></param>

/// <returns>

/// ส่งข้อความกลับให้ไคลน์เอ็นต์ เมื่อเพิ่มข้อมูลเรียบร้อยแล้ว

/// </returns>

[OperationContract]

public string insertCategory(Category category)

{

string resualt = "";//ตัวแปรเก็บข้อความ เพื่อส่งให้ไคลเอ็นต์เมื่อทำงานแล้ว

try

{

using (DataClassesDataContext db = new DataClassesDataContext())

{

//สร้าง อ็อบเจกต์ Category ใหม่

Category cat = new Category()

{

//ถ่ายค่า category ที่ไคลเอ็นต์ส่งมาให้อ็อบเจ็กต์ cat ที่สร้างใหม่

CategoryID = category.CategoryID,

CategoryName = category.CategoryName,

Description = category.Description,

Picture = category.Picture

};

//เพิ่มอ็อบเจ็กต์ใหม่ดังกล่าวเข้าไปใน อ็อบเจ็กต์ Categories (บันทึกข้อมูลบนหน่วยความจำของระบบ)

db.Categories.InsertOnSubmit(cat);

//บันทึกข้อมูลจริงลงตาราง

db.SubmitChanges();

//เก็บข้อความแสดงให้ไคลเอ็นต์รู้ว่าเพิ่มข้อมูลใหม่เรียบร้อย

resualt = "Insert Category completed…";

}

}

catch (System.Exception e)

{

//เก็บข้อความเมื่อเกิดข้อผิดพลาด

resualt = "Insert Category Error…" + e.Message;

}

//ส่งข้อความแสดงการทำงานกลับให้ไคลเอ็นต์

return resualt;

}

/// <summary>

/// เมธอด deleteCategory(int categoryID)

/// ลบข้อมูลในอ็อบเจ็กต์ Categories ตาม categoryID

/// </summary>

/// <param name="categoryID"></param>

/// <returns>

/// ส่งข้อความกลับให้ไคลน์เอ็นต์ เมื่อลบข้อมูลเรียบร้อยแล้ว

/// </returns>

[OperationContract]

public string deleteCategory(int categoryID)

{

string resualt = "";

try

{

using (DataClassesDataContext db = new DataClassesDataContext())

{

//ดึงข้อมูล Category ตาม CategoryID ที่ไคลเอ็นต์ร้องขอ

var cs = from c in db.Categories where c.CategoryID == categoryID select c;

//ลบข้อมูลออก (ลบข้อมูลในหน่วยความจำของระบบ)

db.Categories.DeleteAllOnSubmit(cs);

//ลบข้อมูลจริงออกจากตาราง

db.SubmitChanges();

//เก็บข้อความแสดงให้ไคลเอ็นต์รู้ว่าเพิ่มข้อมูลใหม่เรียบร้อย

resualt = "Delete Category completed…";

}

}

catch (System.Exception e)

{

//เก็บข้อความเมื่อเกิดข้อผิดพลาด

resualt = "Delete Category Error…" + e.Message;

}

//ส่งข้อความแสดงการทำงานกลับให้ไคลเอ็นต์

return resualt;

}

}

 

ลิสต์ติ้งที่ 2: โค้ตฝั่งไคลเอ็นต์

Page.xaml.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Net;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Animation;

using System.Windows.Shapes;

namespace CRUD_SL2b2_WCF_LINQ

{

public partial class Page : UserControl

{

string mode = "";//เก็บสถานะ เมื่อผู้ใช้งานกดปุ่มแก้ไข(Edit) หรือเพิ่ม(New)

public Page()

{

InitializeComponent();

Loaded += new RoutedEventHandler(Page_Loaded);

}

//เคลียร์ข้อมูลบน TextBox ให้ว่าง

private void clearData()

{

txtCategoryID.Text = "";

txtCategoryName.Text = "";

txtDescription.Text = "";

mode = "";

}

void Page_Loaded(object sender, RoutedEventArgs e)

{

//เมธอดเคลียร์ข้อมูลบน TextBox

clearData();

//เมธอดดึงข้อมูล

LoadData();

//กำหนดสีเทาอ่อน(LightGray)บน Background ของ TextBox

txtCategoryID.Background = new SolidColorBrush(Colors.LightGray);

txtCategoryName.Background = new SolidColorBrush(Colors.LightGray);

txtDescription.Background = new SolidColorBrush(Colors.LightGray);

//กำหนดให้ TextBox สามารถอ่านอย่างเดียว

txtCategoryID.IsReadOnly = true;

txtCategoryName.IsReadOnly = true;

txtDescription.IsReadOnly = true;

}

private void LoadData()

{

lblMessage.Text = "Loading Category Data…";

ServiceReference1.ServiceClient svc = new CRUD_SL2b2_WCF_LINQ.ServiceReference1.ServiceClient();

svc.GetCategoryAllCompleted += new EventHandler<CRUD_SL2b2_WCF_LINQ.ServiceReference1.GetCategoryAllCompletedEventArgs>(svc_GetCategoryAllCompleted);

svc.GetCategoryAllAsync();

}

void svc_GetCategoryAllCompleted(object sender, CRUD_SL2b2_WCF_LINQ.ServiceReference1.GetCategoryAllCompletedEventArgs e)

{

datagridCategory.ItemsSource = e.Result;

lblMessage.Text = "Load Category data completed…";

}

private void btNew_Click(object sender, RoutedEventArgs e)

{

clearData();

mode = "New";

//กำหนดสีขาว(White)บน Background ของ TextBox

txtCategoryName.Background = new SolidColorBrush(Colors.White);

txtDescription.Background = new SolidColorBrush(Colors.White);

//กำหนดให้ TextBox สามารถป้อนข้อมูลได้

txtCategoryName.IsReadOnly = false ;

txtDescription.IsReadOnly = false;

}

private void btEdit_Click(object sender, RoutedEventArgs e)

{

mode = "Edit";

//กำหนดสีขาว(White)บน Background ของ TextBox

txtCategoryName.Background = new SolidColorBrush(Colors.White);

txtDescription.Background = new SolidColorBrush(Colors.White);

//กำหนดให้ TextBox สามารถป้อนข้อมูลได้

txtCategoryName.IsReadOnly = false;

txtDescription.IsReadOnly = false;

}

private void btSave_Click(object sender, RoutedEventArgs e)

{

//ประกาศตัวแปรอ็อบเจ็กต์ cat เป็นประเภท Category และกำหนดค่าเริ่มต้นเป็น null

CRUD_SL2b2_WCF_LINQ.ServiceReference1.Category cat = null;

//ประกาศตัวแปรอ็อบเจกต์ svc เป็นประเภท ServiceClient และกำหนดค่าเริ่มต้นเป็น null

ServiceReference1.ServiceClient svc = null;

switch (mode)

{

case "New"://โหมดเพิ่มข้อมูล

//เอาตัวแปรอ็อบเจ็กต์ cat มาทำการสร้างอ็อบเจ็กต์ ใหม่

cat = new CRUD_SL2b2_WCF_LINQ.ServiceReference1.Category();

//ผ่านค่าจาก TextBox แต่ละตัวให้พรอเพอร์ตี้ของมัน

cat.CategoryName = txtCategoryName.Text;

cat.Description = txtDescription.Text;

cat.Picture = null;//เนื่องจากพรอเพอร์ตี้ Picture เป็นข้อมูลรูปภาพ (Binary)บทความนี้จะไม่ขอกล่าวถึง

//เอาตัวแปรอ็อบเจ็กต์ svc มาสร้างอ็อบเจ็กต์ใหม่

svc = new CRUD_SL2b2_WCF_LINQ.ServiceReference1.ServiceClient();

//สร้างอีเว้นต์แฮนเลอร์ (EventHandler) เพิ่มข้อมูลให้มัน

svc.insertCategoryCompleted += new EventHandler<CRUD_SL2b2_WCF_LINQ.ServiceReference1.insertCategoryCompletedEventArgs>(svc_insertCategoryCompleted);

//ผ่านอ็อบเจ็กต์ cat เข้าไปในเมธอด insertCategoryAsync

svc.insertCategoryAsync(cat);

break;

case "Edit"://โหมดแก้ไขข้อมูล

cat = new CRUD_SL2b2_WCF_LINQ.ServiceReference1.Category();

cat.CategoryID = Convert.ToInt32(txtCategoryID.Text);

cat.CategoryName = txtCategoryName.Text;

cat.Description = txtDescription.Text;

cat.Picture = null;

svc = new CRUD_SL2b2_WCF_LINQ.ServiceReference1.ServiceClient();

svc.updateCategoryCompleted += new EventHandler<CRUD_SL2b2_WCF_LINQ.ServiceReference1.updateCategoryCompletedEventArgs>(svc_updateCategoryCompleted);

//ผ่านอ็อบเจ็กต์ cat เข้าไปในเมธอด updateCategoryAsync

svc.updateCategoryAsync(cat);

break;

}

LoadData();

clearData();

//กำหนดสี Background

txtCategoryID.Background = new SolidColorBrush(Colors.LightGray);

txtCategoryName.Background = new SolidColorBrush(Colors.LightGray);

txtDescription.Background = new SolidColorBrush(Colors.LightGray);

//กำหนดให้ TextBox สามารถอ่านอย่างเดียว

txtCategoryID.IsReadOnly = true;

txtCategoryName.IsReadOnly = true;

txtDescription.IsReadOnly = true;

}

void svc_updateCategoryCompleted(object sender, CRUD_SL2b2_WCF_LINQ.ServiceReference1.updateCategoryCompletedEventArgs e)

{

//โชว์หน้าต่างแสดงข้อความการแก้ไขข้อมูลที่ส่งกลับมาจากเซอร์ฟเวอร์

System.Windows.Browser.HtmlPage.Window.Alert(Convert.ToString(e.Result));

}

void svc_insertCategoryCompleted(object sender, CRUD_SL2b2_WCF_LINQ.ServiceReference1.insertCategoryCompletedEventArgs e)

{

//โชว์หน้าต่างแสดงข้อความการเพิ่มข้อมูลที่ส่งกลับมาจากเซอร์ฟเวอร์

System.Windows.Browser.HtmlPage.Window.Alert(Convert.ToString(e.Result));

}

private void btDelete_Click(object sender, RoutedEventArgs e)

{

//แสดงหน้าต่างคำยืนยัน การลบข้อมูล

if (System.Windows.Browser.HtmlPage.Window.Confirm("คุณต้องการลบข้อมูลใช่หรือไม่?…") == true)

{

ServiceReference1.ServiceClient svc = new CRUD_SL2b2_WCF_LINQ.ServiceReference1.ServiceClient();

svc.deleteCategoryCompleted += new EventHandler<CRUD_SL2b2_WCF_LINQ.ServiceReference1.deleteCategoryCompletedEventArgs>(svc_deleteCategoryCompleted);

//ผ่าน CategoryID ที่ต้องการลบเข้าไปในเมธอด deleteCategoryAsync

svc.deleteCategoryAsync(Convert.ToInt32(txtCategoryID.Text));

LoadData();//โหลดข้อมูลใหม่

clearData();//เคลียร์ข้อมูลบน TextBox ทิ้ง

}

}

void svc_deleteCategoryCompleted(object sender, CRUD_SL2b2_WCF_LINQ.ServiceReference1.deleteCategoryCompletedEventArgs e)

{

//โชว์หน้าต่างแสดงข้อความการลบข้อมูลที่ส่งกลับมาจากเซอร์ฟเวอร์

System.Windows.Browser.HtmlPage.Window.Alert(Convert.ToString(e.Result));

}

private void datagridCategory_SelectionChanged(object sender, EventArgs e)

{

if (datagridCategory.SelectedItem is CRUD_SL2b2_WCF_LINQ.ServiceReference1.Category)

{

mode = "";

//ดึงค่าที่เลือกจาก DataGrid ไปใส่บน TextBox แต่ละอัน

//ดึง CategoryID

txtCategoryID.Text = ((CRUD_SL2b2_WCF_LINQ.ServiceReference1.Category)datagridCategory.SelectedItem).CategoryID.ToString();

//ดึง CategoryName

txtCategoryName.Text = (((CRUD_SL2b2_WCF_LINQ.ServiceReference1.Category)datagridCategory.SelectedItem).CategoryName == null) ?

"" : ((CRUD_SL2b2_WCF_LINQ.ServiceReference1.Category)datagridCategory.SelectedItem).CategoryName.ToString();

//ดึง Description

txtDescription.Text = (((CRUD_SL2b2_WCF_LINQ.ServiceReference1.Category)datagridCategory.SelectedItem).Description == null) ?

"" : ((CRUD_SL2b2_WCF_LINQ.ServiceReference1.Category)datagridCategory.SelectedItem).Description.ToString();

}

}

}

}

 

แหล่งดาวน์โหลดซอร์สโค้ด:

 

แหล่งข้อมูลอ้างอิง:

 

Source :> จากนิตยสาร CODE IT [สอดอยู่ในเล่ม Windows ITPro ฉบับเดือน ตุลาคม 2551]

เกี่ยวกับ

Seasoned Senior System Analyst & Developer with over a decade of experience in designing, analyzing, and developing highperformance, scalable applications using a wide range of technologies, including Java, Spring Boot, C#, ASP.NET, MVC, React.js, Kubernetes, Microservices, PostgreSQL, MySQL, Oracle, and Microsoft SQL. Notable Achievements: Consistently delivered projects on time and within budget, ensuring client satisfaction and project success. Demonstrated versatility in working both independently and as a valuable team member, contributing to collaborative achievements. Honored with the prestigious "Employee of the Year" award in 2012 for exceptional dedication and outstanding performance. Recognized as a Microsoft Most Valuable Professional (MVP) for significant contributions to the software development community. My Commitment: I am committed to innovation, excellence, and solving complex technical challenges. I take pride in my ability to consistently deliver robust and efficient software solutions that meet and exceed the expectations of clients and stakeholders.

เขียนใน Silverlight

ใส่ความเห็น

In Archive