以前寫LINQ時總是沒辦法寫得很順,一直覺得寫SQL還較來的方便快速。但最近碰到客戶因為在DB端塞太多商業邏輯(SP、FUN等),導致DB Server效能有點差,因此希望盡量減少SQL的複雜程度,讓AP端也幫忙處理一些邏輯。藉此我練習許多LINQ寫法,也多虧這次經驗我開始對LINQ熟絡起來。
簡單案例:where、orderby
//目標:抓出大於5的數並排序
int[] iArray = { 2, 6, 4, 3, 1, 0, 5, 7, 9, 8 };
//Query syntax:
IEnumerable<int> EnuIResult1 = from n in iArray
where n > 5
orderby n
select n;
//Method syntax:
var EnuIResult2 = iArray.Where(i => (i > 5 )).OrderBy(i => i);
雖然以上兩種寫法(EnuIResult1、EnuIResult2)得到的結果是一樣,但我個人比較喜歡Method syntax,且在處理複雜的邏輯也比較方便。
複雜案例:GroupJoin(Left Join)、GroupBy、Select
首先是測試資料
DataTable dt1 = new DataTable();
dt1.Columns.Add("學生ID", typeof(int));
dt1.Columns.Add("小考科目", typeof(string));
dt1.Columns.Add("小考分數", typeof(int));
dt1.Rows.Add(new object[] { 1, "國文", 90 });
dt1.Rows.Add(new object[] { 1, "數學", 86 });
dt1.Rows.Add(new object[] { 1, "自然", 78 });
dt1.Rows.Add(new object[] { 2, "國文", 83 });
dt1.Rows.Add(new object[] { 2, "數學", 99 });
dt1.Rows.Add(new object[] { 2, "自然", 88 });
DataTable dt2 = new DataTable();
dt2.Columns.Add("學生ID", typeof(int));
dt2.Columns.Add("姓名", typeof(string));
dt2.Rows.Add(new object[] { 1, "張三"});
dt2.Rows.Add(new object[] { 2, "李四" });
DataTable dtResult = new DataTable();
dtResult.Columns.Add("學生ID", typeof(int));
dtResult.Columns.Add("姓名", typeof(string));
dtResult.Columns.Add("十進制", typeof(decimal));
//目標:整理並列出每位學生平均
var data = dt1.AsEnumerable()
.GroupJoin(dt2.AsEnumerable(), m=> m.Field<int>("學生ID"), d=> d.Field<int>("學生ID"), (m,d) =>
{ //類似 LEFT JOIN(dt1為左表、dt2為右表)
DataRow row = dtResult.NewRow();
row["學生ID"] = m.Field<int>("學生ID");
row["姓名"] = d.FirstOrDefault()?.Field<string>("姓名") ?? ""; //在對應dt2資料時都是用Group概念
row["十進制"] = Convert.ToDecimal(m.Field<int>("小考分數"));
return row;
})
.GroupBy(r => new {ID = r.Field<int>("學生ID") }) //把資料依照條件塞進Group裡
.Select(r =>{
var row = dtResult.NewRow();
row["學生ID"] = r.Key.ID;
row["姓名"] = r.FirstOrDefault()?.Field<string>("姓名") ?? "";
row["十進制"] = Math.Round(r.Sum(r1 => r1.Field<decimal>("十進制")) / r.Count(),2); //算出平均
return row;
});
dtResult = data.CopyToDataTable<DataRow>(); //轉回Table
還有較少用到 SelectMany:用途和GroupBy相反(把集合的資料展開)。
結語:之前寫LINQ不順主要還是因為把它當作SQL寫才會有卡住的感覺。
但如果用物件的方式去理解LINQ每一段就會發現合理處,寫起來也會比較順。
SQL處理的是表、LINQ處理的是物件,只要能夠去體會這點就會發現LINQ也不過是資料整理的語法糖。
沒有留言:
張貼留言