'เตรียมข้อมูล Data1 ให้มี 7 row ตั้งแต่ 0-6
Dim dt1 As New Data.DataTable("Data1")
Dim dr1 As DataRow = Nothing
dt1.Columns.Add(New Data.DataColumn("ID"))
dt1.Columns.Add(New Data.DataColumn("Name"))
For iRecord As Integer = 0 To 6
dr1 = dt1.NewRow()
dr1.Item("ID") = iRecord
dr1.Item("Name") = "Test" & iRecord
dt1.Rows.Add(dr1)
Next
'เตรียมข้อมูล Data2 ให้มี 7 rows ตั้งแต่ 4 - 10
Dim dt2 As New Data.DataTable("Data2")
Dim dr2 As DataRow = Nothing
dt2.Columns.Add(New Data.DataColumn("ID"))
dt2.Columns.Add(New Data.DataColumn("Name"))
For iRecord As Integer = 4 To 10
dr2 = dt2.NewRow()
dr2.Item("ID") = iRecord
dr2.Item("Name") = "Test" & iRecord
dt2.Rows.Add(dr2)
Next
ทีนี้ถ้าเราอยากจะหาเฉพาะ DataRow ของ Data1 ที่ไม่ซ้ำกับใน Data2 เราสามารถสั่ง Data1 ExceptRow Data2 ได้ครับ แต่ก่อนอื่นเราต้องแปลง DataTable ให้เป็น Enumerable ก่อนเพราะว่าคำสั่ง Except ไม่มีใน Extension Method ของ DataTable ครับ แต่มีใน System.Linq.Enumerable
Dim r1 = dt1.AsEnumerable()
Dim r2 = dt2.AsEnumerable()
ตัว r1 และ r2 จะมี type เป็น System.Data.EnumerableRowCollection(Of System.Data.DataRow) ครับ ทีนี้เราจะเห็นมี Extension Method ชื่อ Except ให้เรียกใช้ได้แล้ว
Dim ExceptResult = r1.Except(r2, DataRowComparer.Default)
Dim IntersectResult = r2.Intersect(r1, DataRowComparer.Default)
จะสังเกตุว่าผมใส่ DataRowComparer.Default เป็น parameter ด้วย สำหรับ Comparer นั้นเราอาจจะเขียนเองก็ได้ครับ ถ้าเรามีเงื่อนไขในการเปรียบเทียบ DataRow ของเราเอง เช่นต้องการเทียบเฉพาะ Primary Key หรือเฉพาะบาง field เป็นต้นครับ ทีนี้ type ของ ExceptResult จะเป็น
System.Collections.Generic.IEnumerable(Of System.Data.DataRow) ครับ จากตัวอย่างข้างต้น ค่าที่ได้ของ ExceptResult จะมี 4 DataRows นั่นคือ ID ตั้งแต่ 0-3
ส่วนบรรทัดต่อมา ผมลองคำสั่ง Intersect นั่นคือ เอาเฉพาะข้อมูลที่เหมือนกันระหว่าง 2 EnumerableRowCollection ผลลัพธ์ก็จะได้ 3 DataRows คือ ID ตั้งแต่ 4-6 นั่นเอง
ถ้าผมแก้จาก
dr2.Item("Name") = "Test" & iRecord
เป็น
dr2.Item("Name") = "Test2" & iRecord
แล้วลองรันใหม่ จะพบว่า ExceptResult.Count = 7 นั่นคือข้อมูลทั้งหมดของ dt1 และ IntersectResult.Count = 0 เพราะว่าเราใช้ DataRowComparer.Default อย่างที่บอกครับ ดังนั้นแต่ละ row ถึงจะมี ID เดียวกัน เป็นข้อมูลใน field อื่นไม่เหมือนกัน ก็จะถือว่าเป็น row นั้น ไม่เหมือนกันครับ
คราวนี้มาลองเล่นกันต่อครับ กำลังสนุกเลย
Dim dtResult = ExceptResult.CopyToDataTable()
dtResult.TableName = "dtResult"
dt1.Rows(0).Delete()
dt2.Rows(1).Delete()
บรรทัดแรกผมใช้ Extension Method ชื่อ CopyToDataTable ก็ตรงตัวครับ คือมันจะ copy DataRows ไปสร้าง DataTable ใหม่ สำหรับคำส่งนี้ถ้าเราส่ง DataTable ไปเป็น parameter มันจะ copy DataRows ไปยัง DataTable ตัวนั้นๆแทนครับ
ต่อมาผมลองสั่งลบแถวแรก ของ dt1 และลบแถวที่สองของ dt2 ทีนี้ลองมา debug ดูข้อมูลใน dt1, dt2, r1, r2, ExceptResult, IntersectResult จะพบว่าเมื่อเราสั่งลบ Datarows แล้ว มันจะมีผลต่อ r1, r2, ExceptResult, IntersectResult ครับ แต่มันไม่มีผลต่อ dtResult ครับ ดังนั้นตอนนี้ค่าของ dtResult จะไม่เท่ากับ ExceptResult แล้ว
ที่เป็นแบบนี้เพราะว่า Except() กับ Intersect() นั้นใช้ความสามารถของ Yield Return นั่นเองครับ ไอ้เจ้า Yield Return นี่มันสุดยอดจริงๆ เสียดายที่ VB2008 ไม่สามารถใช้ Yield Return ได้ครับ สำหรับผู้ที่อยากรู้เรื่อง Yield Return ลอง search ใน google ดูครับ ผมเคยอ่านที่ www.coredeveloper.net แต่วันนี้มันเข้าไปเวบนี้ไม่ได้ซะละ
ไม่มีความคิดเห็น:
แสดงความคิดเห็น