แปล SQL เป็น Linq - Part I

Posted 06/10/2009 21:35 by chaowman

สวัสดีครับ ผมชื่อ chaowman ได้รับเกียรติจาก coreadmin ให้มาร่วมเขียนด้วยกัน
เดิมที ผมก็อยากเขียนเรื่องเกี่ยวกับ Windows Mobile แบบท่าน coreadmin
แต่เผอิญมือถือที่ใช้ยังเป็นรุ่นน้องโบ(ราณ)อยู่เลยครับ image
ความรู้อะไรเกี่ยวกับ Windows Mobile ก็แทบไม่มี
เลยขอฉีกแนวไปทาง Server Side ซะหน่อย image
ถือเป็นการแตก Line ของ CoreSharp ละกันครับ

คุณรู้มั้ยครับว่า Microsoft มีความตั้งใจจะ Map ระหว่าง Table กับ Object ตั้งนานละ 
และก็มีความตั้งใจว่า วันนึง เราจะสามารถ Query Object ต่าง ๆ ได้เหมือนกับ Query Database
ซึ่งวันนี้เราก็สามารถทำได้อย่างง่าย ๆ แล้วล่ะครับ ด้วย Technology ที่ชื่อ Linq
ซึ่งไม่ว่าจะ Database หรือ Object หรือ แม้แต่ XML เราก็สามารถ Query ได้ด้วยภาษาเดียวเลยครับ

ก่อนที่เราจะไปถึง Linq เราก็มาเข้าใจสิ่งที่เราจะ Query กันก่อน
เรามาดู Table ที่อยู่ใน Database กัน

 image

ถ้าเปรียบเทียบกับ Table 1 record ก็เท่ากับ 1 object ใน .NET
โดย Field ต่าง ๆ ก็จะเท่ากับ Property
เช่น Field CustomerID ซึ่งมี Type เป็น nvarchar ก็เท่ากับ Property ที่มี Type เป็น string
ซึ่งสิ่งที่จะ Represent 1 record ใน Table ก็คือ Class ข้างล่างนี้ครับ

image

แต่มีแค่ object เดียวเรายัง Query ไม่ได้ครับ
เพราะสิ่งที่เราจะ Query มันต้องเป็น Collection
โดย 1 collection มันก็เปรียบได้กับ 1 Table ครับ

image 

Collection ใน .NET มีมากมายหลายแบบ
ซึ่ง Collection ก็คือ Object ที่เราสามารถใช้ foreach เรียก item แต่ละตัวออกมาได้นั่นเอง
ซึ่งตัวอย่างของ Customer Collection ต่าง ๆ มีดังนี้ครับ

image 

ซึ่งไม่ว่าจะเป็น Array, List หรือ Collection ต่าง ๆ ก็สามารถ Query ได้หมดครับ
ทีนี้เรามาเริ่ม Linq กันเลยดีกว่า

 

SELECT – All fields

เริ่มจากการเรียกทุก Field และเรียกทุก Record ใน Table เราเขียนอย่างนี้

image 

เราใช้ * (เครื่องหมายดอกจัน) แทนการเรียกทุก Field
ส่วนใน Linq เราเขียนอย่างนี้

image

ทุกครั้งที่เราจะเริ่มเขียน Linq เราต้องเอา "from" ขึ้นต้นเสมอ
ตามด้วยชื่อตัวแปรของ Collection นั้น ๆ ซึ่งในที่นี้คือตัว "c" (จะใช้ชื่ออะไรก็ได้ไม่จำเป็นต้องเป็น "c")
ในการเลือกทุก Property เราไม่ต้องใช้ "select c.*" (มีเครื่องหมายดอกจัน)
ใช้แค่ "select c" เฉย ๆ

เมื่อคุณเอา "result" ไปโยนใส่ foreach คุณก็จะได้ customer แต่ละ customer ใน list นั้น

 

SELECT – Single field

ต่อมาถ้าเราอยากจะเรียกเฉพาะ id ของทุก Record ใน Table เราเขียนอย่างนี้

image

เราใช้ชื่อ alias ของ Table ตามด้วยชื่อ Field ซึ่งก็คือ c.CustomerID
ซึ่งใน Linq เราก็เขียนแทบเหมือนกัน ดังนี้

image

เราใช้ชื่อตัวแปรตามด้วยชื่อ Property เช่นเดียวกัน
และเมื่อโยน "result" ใส่ foreach คุณก็จะได้ string ที่มีค่าเป็น CustomerID

 

SELECT – Multiple fields

แน่นอนว่าคุณคงไม่ได้อยากเรียกใช้แต่ Field เดียว
การเรียกหลาย ๆ Field ใน SQL เราเขียนอย่างนี้ครับ

image 

เราแค่ใส่ , (Comma) ขั้นในแต่ละ Field ที่เราจะเรียกออกมา
ซึ่งใน Linq นั้นการเรียกหลาย ๆ Property นั้น
ใน VB กับ C# จะต่างกัน

ใน VB นั้น จะเขียนคล้ายกับ SQL เลยครับ เขียนอย่างนี้

image

ส่วน C# เราจำเป็นต้องมีคำว่า new และ { } (วงเล็บปีกกา) ครอบเอาไว้
เพื่อแสดงถึงการสร้าง anonymous type

image 

และเมื่อเราเอา result ไปโยนใส่ foreach
เราก็จะได้ object ที่มี property 3 ตัว ซึ่งก็คือ CustomerId, CompanyName,และ ContactName

 

SELECT – Custom field

สมมติถ้าคุณเกิดอยากสร้าง Field ใหม่ โดยคำนวนจาก Field เดิม
หรือถ้าคุณอยากเปลี่ยนชื่อ Field ใหม่ คุณสามารถเขียนได้ตามนี้

image 

คุณสามารถเอา Field ต่าง ๆ มาบวก ลบ คูณ หาร ใส่ฟังค์ชั่นได้ตามสบาย
และก็สามารถกำหนดชื่อ Field ใหม่ด้วยคำว่า "as"

ใน VB คุณสามารถเขียนคล้าย ๆ SQL ดังนี้

image

ให้เอาชื่อ Field ตั้ง ตามด้วย = (เท่ากับ)

ส่วน C# ก็คล้าย ๆ กันแต่ต้องเอา new ครอบ

image

และเมื่อเราเอา result ไปโยนใส่ foreach
เราก็จะได้ object ที่มี property 2 ตัว ซึ่งก็คือ CustomerId, และ FullAddress

 

SELECT - Top

บางทีเราไม่ได้ต้องการข้อมูลทั้งตาราง
เราอาจจะอยากได้ข้อมูลแค่ 10 อันแรกมาแสดง
ใน SQL เราใช้คำสั่ง Top เพื่อกำหนดจำนวนข้อมูลที่ต้องการ

image 

ในภาษาของ .NET เราใช้คำว่า Take
ใน VB เราสามารถเขียนง่าย ๆ อย่างนี้ครับ

image

แค่เอาคำว่า Take ต่อท้ายแล้วตามด้วยจำนวนที่ต้องการ
ใน VB เราไม่จำเป็นต้องจบประโยคด้วย SELECT ทุกครั้ง
ซึ่งถ้าไม่มี SELECT หมายถึงเราจะ Query ทุก Field

ใน C# ไม่มีคำสั่งที่เป็น Linq ครับ
เราเลยต้องเขียน Method อย่างนี้

image

ใช้วงเล็บครอบ Linq แล้วตามด้วย Method ชื่อ Take
และส่งจำนวน Record ที่ต้องการเข้าไป

 

SELECT - Row number

สมมติว่าคุณกำลังเขียน DataGrid บน Web เพื่อแสดงลูกค้าทั้งหมด
แต่ทีนี้จำนวนลูกค้ามีเยอะมาก ทำให้คุณต้องแบ่งเป็นหน้า ๆ
ซึ่งหน้าแรกไม่ยาก เราแค่ใช้คำสั่ง Take เอา Record เฉพาะด้านบน
แต่หน้า 2 ขึ้นไปเราจะทำยังไงครับ

ในฐานข้อมูล Oracle มี keyword ที่มีประโยชน์มากชื่อ rownum
เราสามารถเลือกช่วงของข้อมูลโดยใช้ rownum

image 
(ถ้าคุณ Query ใน SQL Server คุณอาจจะใช้ function row_number)

ทีนี้ใน Linq คุณต้องมาคำนวนนิดนึง
ซึ่งใน Linq ไม่มีคำสั่งสำเร็จรูปสำหรับเรียกใช้ row number
คุณต้องคำนวนว่าคุณต้องใช้กี่ row
ซึ่งถ้าตามตัวอย่างด้านบนก็ใช้ทั้งหมด 10 rows (row ที่ 26 ถึง 35)

ใน .NET เราจะใช้คำว่า Skip เพื่อข้ามจำนวน Record ที่ต้องการ
ใน VB เขียนอย่างนี้ครับ

image 

คำสั่งด้านบนหมายถึงข้ามไป 25 records (ซึ่งก็คือ record ที่ 26)
แล้วเอา 10 records (ซึ่งก็คือ record ที่ 26 ถึง 35)

ใน C# เราไม่มีคำสั่งที่เป็น Linq
จำเป็นที่ต้องใช้ Method ชื่อว่า Skip

image 

ใน Method ชื่อ Skip ส่งจำนวน Record ที่ต้องการโดดข้ามเข้าไป

 

SELECT - Distinct

สุดท้ายแล้วครับสำหรับ Part นี้
บางครั้งข้อมูลใน Collection อาจจะมีข้อมูลซ้ำกันอยู่
เช่น มีชื่อลูกค้าเดียวกันใน List จำนวนหลาย Record
ใน SQL คุณสามารถสั่ง Distinct เพื่อให้ตัด Record ที่ซ้ำออกไป
ซึ่งสามารถเขียนได้อย่างนี้ครับ

image

จากตัวอย่างด้านบน เป็นการเลือกเฉพาะ ContactName
เนื่องจากเราใส่ Distinct เข้าไป
ดังนั้นรายการที่คืนกลับมา จะเป็นรายชื่อที่ไม่ซ้ำกันเลย
แม้ว่าลูกค้าอาจจะมีชื่อซ้ำกันก็ตาม

ใน VB ก็เขียนแบบ Simple ๆ ตามเคยครับ

image 

แค่เติมคำว่า Distinct ต่อท้าย
ข้อมูลที่ซ้ำก็หายไป

ใน C# ไม่มีคำสั่งที่เป็น Linq ตามเคย
ซึ่งคุณต้องใช้ Method ที่ชื่อ Distinct ครับ

image 

เท่านี้ Record ที่คืนค่ามา ก็ไม่มีข้อมูลที่ซ้ำกันครับ

จากหลาย ๆ ตัวอย่างจะเห็นว่า
ภาษาของ VB ด้าน Linq จะครบถ้วนมากกว่า C#

ตอนหน้าเรามาต่อกันครับ
สำหรับวิธีใช้ WHERE และ วิธีใช้ JOIN แบบต่าง ๆ ใน Linq

About chaowman

หาอะไรอยู่หรือจ๊ะ?

ร่วมให้กำลังใจนักเขียน

อ่านแล้วชอบใจ อยากให้กำลังใจกับผู้แต่งบทความนี้ ขอเชิญร่วมให้กำลังใจผ่าน Paysbuy/Paypal นะครับ ปลอดภัยเพราะทำงานผ่าน SSL และไม่มีค่าใช้จ่ายเพิ่มเติมครับ เว็บเราให้นักเขียน 100% ครับ

Comment ระบบเก่า

 

อ่าน said:

ต่อจาก Post ที่แล้ว ครับ ผมได้เกริ่นวิธีสำหรับในการ SELECT Field แบบต่าง ๆ ไปแล้ว คราวนี้ เรามาดูกันว

October 15, 2009 5:55 PM
 

frontpage said:

  คุณยังรู้สึกว่า ตอนนี้เขียนโปรแกรมทำอะไรที่ต้องแสดงข้อมูลที เป็นเรื่องยุ่งยากน่าเบื่อหรือเปล่า

March 21, 2010 3:49 AM
(required)  
(optional)
(required)  
Add

DisQUS Comment (ยังเอ๋อๆ อยู่)

blog comments powered by Disqus