สวัสดีอีกครั้งครับ วันนี้ก็เป็นหัวข้อที่น่าสนใจทีเดียวมาเริ่มกันเลย..
คอร์สนี้สำหรับผู้ที่เขียน .NET ไม่ว่าจะ VB หรือ C# และเคยทำงานร่วมกับ SQL XML Textfile มาครับ ประกอบไปด้วย
- เข้าใจ LINQ
- ปูพื้นฐานก่อนใช้ LINQ
- LINQ as language extension
- Query Operators
- Query Expressions
- LINQ to SQL
- LINQ to Textfile
- LINQ to XML
- Future of LINQ (maybe)
ก็คงมีกันหลาย part นะครับ ไม่เป็นไรครับ เพื่อความรู้ 
LINQ(Language Integrated Query) นั้นคืออะไร สำคัญฉไน เหตุใดใยฉันจึงควรรู้ คำตอบคือ สำคัญครับ สำหรับ Developer ที่ต้องการให้สรรพสิ่งง่ายดายและรวดเร็วขึ้น ง่านต่อการ maintain code อีกทั้งยังมี performance ที่น่าพึงพอใจอีกด้วย (ทั้งนี้ส่วนใหญ่มันขึ้นอยู่กับคนเขียนด้วย ไม่ได้ LINQ อย่างเดียว) รับรองเลยครับว่า ชีวิตท่านจะสะดวกสบายขึ้นจริงๆ เราจะแบ่งอธิบายเป็นข้อๆเพื่อความเข้าใจง่าย
LINQ คือ?
- คือ language extension(ตัวต่อยอดของภาษา) อย่างหนึ่งช่วยทำให้ การเขียนโปรแกรม C# หรือ VB ง่ายดายยิ่งขึ้น
- คือ toolset ที่ทำให้การทำงานกับ data ต่างๆ สะดวกมากๆยิ่งขึ้น จำแนกออกเป็นหลายประเภท เช่น LINQ to SQL , LINQ to XML ,LINQ to Textfile ไว้ค่อยว่ากัน
ภาพนี้จะช่วยให้เข้าใจง่ายขึ้น(หรือยากขึ้น)

ใน Visual Studio 2008 นั้นมีการใช้ LINQ อย่างแพร่หลาย(หรือหลายคนจะใช้โดยไม่รู้ตัว) สังเกตุจากทุกครั้งจะมีการ include System.Linq โดยอัตโนมัติเวลาสร้างหน้าcode ใหม่
LINQ ทำไม?
- คุณเคยไหมเวลาเขียน code แล้วรู้สึกว่า ทำไมต้องการนั่งเขียนอะไรแบบเดิมๆ ซํ้าๆ วนลูปแบบเดิมๆแต่แค่เปลี่ยนชื่อ code ที่ยาวยืด(plumbing code) ต้องมา iterate ลูปกันจนเบื่อ ทั้งหมดนี้ LINQ ช่วยท่านได้
- คุณรู้สึกไหมว่าการเชื่อมต่อกับdatabaseทำไมado.net ถึงได้วุ่นวายนักต้องเขียนระบุ connection command ต้องรู้จักภาษา sql ละเอียด ต้อง map relational data เข้ากับ object ใน code เราอีก
- ต้องศึกษาภาษาเฉพาะทางสำหรับ xml ซึ้งมีมากมาย อาทิ XPath XQuery NHerbinate(ตัว mapping .NET code กับ XML) หรืออะไรก็ตาม ทำไมหละๆ ไม่ทำให้มันสักหนึ่งอันไปเลย
- ถ้าวันนี้ฉันอยากจะรับdata จาก xml แล้วเอามาเก็บ in memory แล้วเอาไปบันทึกลง sql server database หละ จะต้องเขียนcode กันสักแค่ไหน ช่องว่างตรงนี้แหละคับที่เรียกว่า "impedance mismatch" (อย่าตกใจ ไม่มีอะไรเกี่ยวกับimpedanceในphysics)
- และปัญหาอื่นๆที่ผมนึกไม่ออก
ปัญหาทั้งหมดนี้ LINQ can help you!
ปูพื้นฐานก่อน LINQ
ยังไงๆซะ คุณควรจะมีความรู้ภาษาระดับ advance .net มาก่อนที่จะเข้าใจ LINQ ได้ครับ ไม่งั้นคุณจะเป็นแค่ ผู้ใช้ ไม่ได้ ผู้ที่เข้าใจจริงๆครับ สำหรับสิ่งเหล่านี้ก็เป็นพื่นฐานที่ผมจะ refresh ให้คุณ
- Implicit typed local variables : ง่ายๆ เช่น var i = 5; ตัวนี้เรียก Implicit typed local variables แทนที่จะ int i =5; เพราะ compiler จะอ้างอิงว่าtypeของvarจาก expression ของมันซึ่งคือ 5 ทั้งนี้รวมไปถึงตัวแปรชนินอื่นๆอาทิ var s = "Hello"; var numbers = new[] {1,2,3,4}; var dicts = new Dictionary<int,MyData>(); เป็นต้นลองเอาไปทดลองใช้กับ code ดูครับ เช่น
var lines = new LinesFromDatabase();
foreach(var line in lines.GetOneLine()){
...
}
- Object Initializers : สมมติมี
public class Student{
public string ID{get; set;}
public string Name{get; set;}
}
ปกติเราจะประกาศ Object สักอันก็ต้องทำแบบนี้ใช่มั้ยครับ
public class StudentSample{
Student stu1 = new Student();
stu1.ID = "50880xx";
stu1.Name = "Ochin TheGang";
}
แต่ Object Initializers คุณสามารถ
public class StudentSample{
Student stu1 = new Student(){ID="50880xx",Name="Ochin TheGang"};
}
ต่อไปเวลาเขียนExceptionก็สะดวกแล้ว แค่ throw new Exception("your message"){Source="exception source"};
เสริม : Collection Initializers คล้าย Object Initializers แหละครับ ไม่มีใช้ใน LINQ นะ สมมติเราอยากได้ List ของ Student
แบบเก่า
var stuList = new List<Student>();
stuList.Add(new Student{ID="123",Name="dd xx"});
stuList.Add(new Student{ID="567",Name="yy zz"});
แต่ Collection Initializers โดยความฉลาดของ compiler ทำให้ไม่ต้องเขียน Add ให้มากมาย
var stuList = new List<Student>(){new Student{ID="123",Name="dd xx"},new Student{ID="567",Name="yy zz"}}
- Lambda Expressions : สำหรับตัวนี้ก็ต้องมีความเข้าใจใน Delegate ก่อนครับ เพราะ Lambda Expressions ง่ายๆก็คือการทำให้ Delegate สะดวกยิ่งขึ้นนั่นเอง
Delegates คือการ อ้างอิง pointer ไปที่ method ตัวอย่างง่ายๆคือเราไม่ได้อยากส่งแค่ value เข้าไปใน function แต่เราอยากส่ง function เข้าไปใน function เพื่อความเ้ข้าใจง่าย สมมติว่าเราอยากได้ customer ที่รวยโดยมีเงินpocket money มากกว่า 100000บาท
static string GetTotalMoneyInStringFormat(Func<Customer,Boolean> checkIfGreaterThan){
var richCustomerList = new List<Customer>();
foreach(var customer in GetCustomerListFromSomewhere()){
if(checkIfGreaterThan(customer))
richCustomerList.Add(customer);
}
}
เวลาเราเรียกใช้ function นี้ก็ string output = GetTotalMoneyInStringFormat(delegate(Customer customer){return customer.PocketMoney > 100000}); นี่แหละครับคือ delegate แบบ Anonymous method (คือเขียนmethodแบบ inline scripting) ส่วน delegate แบบธรรมดานั้นไม่ขอพูดถึงแล้วกันครับ เราไม่ได้ pass value เข้าไปแต่เรา pass ให้มันทั้ง function delegate จะมีประโยชน์มากถ้าเรารู้จักใช้ครับ แต่ถ้า overuse จะทำให้มีปัญหาเรื่อง performance ตามมาครับ สำหรับรายละเอียด มี Guru provides ไว้แล้วครับ Memory Leak with delegates and workflow foundation By Omar
สำหรับ Lambda Expressions จะทำให้code เรา concise ขึ้นมากครับ(การเขียนAnonymousข้อเสียคือความเป็นimperativeซึ่งทำให้อ่านยากและยืดยาว แต่lambdaนั้นเรียกว่าเป็นการเขียนแบบfunctional programmingเลยก็ว่าได้) จากตัวอย่างที่ผ่านมาเราสามารถเรียก string output = GetTotalMoneyInStringFormat(cus=>cus.PocketMoney >100000); จบครับ ได้คำตอบเท่ากัน
cus=>cus.PocketMoney >100000 อ่านไดว่า cus "ไปยัง" cus.PocketMoney >100000
lampda expression นั้นแบ่งเป็น 2 แบบ คือ statement lambda เช่น x=>{return x+1;} หรือ cus=>Console.WriteLine(cus.PocketMoney) เป็นต้น กับ expression lambda เช่น x=>x+1 หรือ cus=>cus.PocketMoney เป็นต้น
จากตัวอย่างข้างบน Func< Customer,Boolean> checkIfGreaterThan คงจะสงสัยสิครับว่าคืออะไร Func<Customer,Boolean> คือ delegate type ครับ เราควรจะต้องรู้จัก delegate types เช่น
delegate void Action();
delegate void Action<T1,T2>(T1 args1,T2 args2);
delegate void Action<T1,T2,T3>(T1 args1,T2 args2,T3 args3);
delegate void Action<T1,T2,T3,T4>(T1 args1,T2 args2,T3 args3,T4 args4);
delegate TResult Func<TResult>();
delegate TResult Func<T1,TResult>(T1 args1);
delegate TResult Func<T1,T2,TResult>(T1 args1,T2 args2);
delegate TResult Func<T1,T2,T3,TResult>(T1 args1,T2 args2,T3 args3);
delegate TResult Func<T1,T2,T3,T4,TResult>(T1 args1,T2 args2,T3 args3,T4 args4);
จาก Func<Customer,Boolean> checkIfGreaterThan ของเราเป็นแบบ delegate TResult Func<T1,TResult>(T1 args1); ครับ เข้าใจได้ว่า functionนี้return Boolean รับinputเป็นtype Customer มันจะแสดงความสัมพันธ์ให้เข้าใจอย่างง่ายๆเลยครับ
เพื่อความเข้าใจง่ายว่ามันเกี่ยวกับ lambda expressions ยังไงผมขอยกตัวอย่างความ compatibility เช่น
Func<int,int,double> calculate รับค่าของ (x,y)=>x*y/2; ได้
Action<string> printName รัยค่าของ s=>Console.WriteLine(s); ได้
เป็นต้น ครับ ที่อธิบายอย่างละเอียดเพราะจำเป็นต้องเข้าใจครับ อีกทั้งยังเป็นประโยชน์กับคุณเองในอนาคตด้วย
ยังเหลืออีก 2 อย่างที่ยังไม่ cover สำหรับการปูพื้นฐาน ยังไงก็อดใจรอนะครับ ในฉบับหน้า
- Anonymous Types and Methods
63180f80-2ff4-4abc-ad46-05db15bd1cc9|2|5.0