สวัสดีครับ ผมชื่อ chaowman ได้รับเกียรติจาก coreadmin ให้มาร่วมเขียนด้วยกัน เดิมที ผมก็อยากเขียนเรื่องเกี่ยวกับ Windows Mobile แบบท่าน coreadmin แต่เผอิญมือถือที่ใช้ยังเป็นรุ่นน้องโบ(ราณ)อยู่เลยครับ ความรู้อะไรเกี่ยวกับ Windows Mobile ก็แทบไม่มี เลยขอฉีกแนวไปทาง Server Side ซะหน่อย ถือเป็นการแตก Line ของ CoreSharp ละกันครับ คุณรู้มั้ยครับว่า Microsoft มีความตั้งใจจะ Map ระหว่าง Table กับ Object ตั้งนานละ และก็มีความตั้งใจว่า วันนึง เราจะสามารถ Query Object ต่าง ๆ ได้เหมือนกับ Query Database ซึ่งวันนี้เราก็สามารถทำได้อย่างง่าย ๆ แล้วล่ะครับ ด้วย Technology ที่ชื่อ Linq ซึ่งไม่ว่าจะ Database หรือ Object หรือ แม้แต่ XML เราก็สามารถ Query ได้ด้วยภาษาเดียวเลยครับ ก่อนที่เราจะไปถึง Linq เราก็มาเข้าใจสิ่งที่เราจะ Query กันก่อน เรามาดู Table ที่อยู่ใน Database กัน ถ้าเปรียบเทียบกับ Table 1 record ก็เท่ากับ 1 object ใน .NET โดย Field ต่าง ๆ ก็จะเท่ากับ Property เช่น Field CustomerID ซึ่งมี Type เป็น nvarchar ก็เท่ากับ Property ที่มี Type เป็น string ซึ่งสิ่งที่จะ Represent 1 record ใน Table ก็คือ Class ข้างล่างนี้ครับ แต่มีแค่ object เดียวเรายัง Query ไม่ได้ครับ เพราะสิ่งที่เราจะ Query มันต้องเป็น Collection โดย 1 collection มันก็เปรียบได้กับ 1 Table ครับ Collection ใน .NET มีมากมายหลายแบบ ซึ่ง Collection ก็คือ Object ที่เราสามารถใช้ foreach เรียก item แต่ละตัวออกมาได้นั่นเอง ซึ่งตัวอย่างของ Customer Collection ต่าง ๆ มีดังนี้ครับ ซึ่งไม่ว่าจะเป็น Array, List หรือ Collection ต่าง ๆ ก็สามารถ Query ได้หมดครับทีนี้เรามาเริ่ม Linq กันเลยดีกว่า
เริ่มจากการเรียกทุก Field และเรียกทุก Record ใน Table เราเขียนอย่างนี้ เราใช้ * (เครื่องหมายดอกจัน) แทนการเรียกทุก Field ส่วนใน Linq เราเขียนอย่างนี้ ทุกครั้งที่เราจะเริ่มเขียน Linq เราต้องเอา "from" ขึ้นต้นเสมอ ตามด้วยชื่อตัวแปรของ Collection นั้น ๆ ซึ่งในที่นี้คือตัว "c" (จะใช้ชื่ออะไรก็ได้ไม่จำเป็นต้องเป็น "c") ในการเลือกทุก Property เราไม่ต้องใช้ "select c.*" (มีเครื่องหมายดอกจัน) ใช้แค่ "select c" เฉย ๆ เมื่อคุณเอา "result" ไปโยนใส่ foreach คุณก็จะได้ customer แต่ละ customer ใน list นั้น
ต่อมาถ้าเราอยากจะเรียกเฉพาะ id ของทุก Record ใน Table เราเขียนอย่างนี้ เราใช้ชื่อ alias ของ Table ตามด้วยชื่อ Field ซึ่งก็คือ c.CustomerIDซึ่งใน Linq เราก็เขียนแทบเหมือนกัน ดังนี้ เราใช้ชื่อตัวแปรตามด้วยชื่อ Property เช่นเดียวกัน และเมื่อโยน "result" ใส่ foreach คุณก็จะได้ string ที่มีค่าเป็น CustomerID
แน่นอนว่าคุณคงไม่ได้อยากเรียกใช้แต่ Field เดียว การเรียกหลาย ๆ Field ใน SQL เราเขียนอย่างนี้ครับ เราแค่ใส่ , (Comma) ขั้นในแต่ละ Field ที่เราจะเรียกออกมา ซึ่งใน Linq นั้นการเรียกหลาย ๆ Property นั้น ใน VB กับ C# จะต่างกัน ใน VB นั้น จะเขียนคล้ายกับ SQL เลยครับ เขียนอย่างนี้ ส่วน C# เราจำเป็นต้องมีคำว่า new และ { } (วงเล็บปีกกา) ครอบเอาไว้ เพื่อแสดงถึงการสร้าง anonymous type และเมื่อเราเอา result ไปโยนใส่ foreach เราก็จะได้ object ที่มี property 3 ตัว ซึ่งก็คือ CustomerId, CompanyName,และ ContactName
สมมติถ้าคุณเกิดอยากสร้าง Field ใหม่ โดยคำนวนจาก Field เดิม หรือถ้าคุณอยากเปลี่ยนชื่อ Field ใหม่ คุณสามารถเขียนได้ตามนี้ คุณสามารถเอา Field ต่าง ๆ มาบวก ลบ คูณ หาร ใส่ฟังค์ชั่นได้ตามสบาย และก็สามารถกำหนดชื่อ Field ใหม่ด้วยคำว่า "as" ใน VB คุณสามารถเขียนคล้าย ๆ SQL ดังนี้
ให้เอาชื่อ Field ตั้ง ตามด้วย = (เท่ากับ) ส่วน C# ก็คล้าย ๆ กันแต่ต้องเอา new ครอบ
และเมื่อเราเอา result ไปโยนใส่ foreach เราก็จะได้ object ที่มี property 2 ตัว ซึ่งก็คือ CustomerId, และ FullAddress
บางทีเราไม่ได้ต้องการข้อมูลทั้งตารางเราอาจจะอยากได้ข้อมูลแค่ 10 อันแรกมาแสดงใน SQL เราใช้คำสั่ง Top เพื่อกำหนดจำนวนข้อมูลที่ต้องการ ในภาษาของ .NET เราใช้คำว่า Takeใน VB เราสามารถเขียนง่าย ๆ อย่างนี้ครับ แค่เอาคำว่า Take ต่อท้ายแล้วตามด้วยจำนวนที่ต้องการใน VB เราไม่จำเป็นต้องจบประโยคด้วย SELECT ทุกครั้งซึ่งถ้าไม่มี SELECT หมายถึงเราจะ Query ทุก Fieldใน C# ไม่มีคำสั่งที่เป็น Linq ครับเราเลยต้องเขียน Method อย่างนี้ ใช้วงเล็บครอบ Linq แล้วตามด้วย Method ชื่อ Takeและส่งจำนวน Record ที่ต้องการเข้าไป
สมมติว่าคุณกำลังเขียน DataGrid บน Web เพื่อแสดงลูกค้าทั้งหมดแต่ทีนี้จำนวนลูกค้ามีเยอะมาก ทำให้คุณต้องแบ่งเป็นหน้า ๆซึ่งหน้าแรกไม่ยาก เราแค่ใช้คำสั่ง Take เอา Record เฉพาะด้านบนแต่หน้า 2 ขึ้นไปเราจะทำยังไงครับในฐานข้อมูล Oracle มี keyword ที่มีประโยชน์มากชื่อ rownumเราสามารถเลือกช่วงของข้อมูลโดยใช้ rownum (ถ้าคุณ Query ใน SQL Server คุณอาจจะใช้ function row_number)ทีนี้ใน Linq คุณต้องมาคำนวนนิดนึงซึ่งใน Linq ไม่มีคำสั่งสำเร็จรูปสำหรับเรียกใช้ row numberคุณต้องคำนวนว่าคุณต้องใช้กี่ rowซึ่งถ้าตามตัวอย่างด้านบนก็ใช้ทั้งหมด 10 rows (row ที่ 26 ถึง 35)ใน .NET เราจะใช้คำว่า Skip เพื่อข้ามจำนวน Record ที่ต้องการใน VB เขียนอย่างนี้ครับ คำสั่งด้านบนหมายถึงข้ามไป 25 records (ซึ่งก็คือ record ที่ 26)แล้วเอา 10 records (ซึ่งก็คือ record ที่ 26 ถึง 35)ใน C# เราไม่มีคำสั่งที่เป็น Linqจำเป็นที่ต้องใช้ Method ชื่อว่า Skip ใน Method ชื่อ Skip ส่งจำนวน Record ที่ต้องการโดดข้ามเข้าไป
สุดท้ายแล้วครับสำหรับ Part นี้บางครั้งข้อมูลใน Collection อาจจะมีข้อมูลซ้ำกันอยู่เช่น มีชื่อลูกค้าเดียวกันใน List จำนวนหลาย Recordใน SQL คุณสามารถสั่ง Distinct เพื่อให้ตัด Record ที่ซ้ำออกไปซึ่งสามารถเขียนได้อย่างนี้ครับ จากตัวอย่างด้านบน เป็นการเลือกเฉพาะ ContactNameเนื่องจากเราใส่ Distinct เข้าไปดังนั้นรายการที่คืนกลับมา จะเป็นรายชื่อที่ไม่ซ้ำกันเลยแม้ว่าลูกค้าอาจจะมีชื่อซ้ำกันก็ตามใน VB ก็เขียนแบบ Simple ๆ ตามเคยครับ แค่เติมคำว่า Distinct ต่อท้ายข้อมูลที่ซ้ำก็หายไปใน C# ไม่มีคำสั่งที่เป็น Linq ตามเคยซึ่งคุณต้องใช้ Method ที่ชื่อ Distinct ครับ เท่านี้ Record ที่คืนค่ามา ก็ไม่มีข้อมูลที่ซ้ำกันครับจากหลาย ๆ ตัวอย่างจะเห็นว่าภาษาของ VB ด้าน Linq จะครบถ้วนมากกว่า C#ตอนหน้าเรามาต่อกันครับสำหรับวิธีใช้ WHERE และ วิธีใช้ JOIN แบบต่าง ๆ ใน Linq
ต่อจาก Post ที่แล้ว ครับ ผมได้เกริ่นวิธีสำหรับในการ SELECT Field แบบต่าง ๆ ไปแล้ว คราวนี้ เรามาดูกันว
  คุณยังรู้สึกว่า ตอนนี้เขียนโปรแกรมทำอะไรที่ต้องแสดงข้อมูลที เป็นเรื่องยุ่งยากน่าเบื่อหรือเปล่า