[英]Effectively Using LINQ in C#
我有一個用C#編寫的應用程序。 我有一個對象集合,我需要執行諸如排序和跳轉到對象頁面的任務。 目前,我有這樣的東西:
this.Items = model.Items
.Where(x => x.Id > 0)
.ToList();
if (SortBy == "Name")
{
if (Direction == "Descending")
this.Items = (this.Items.OrderByDescending(x => x.Name)).ToList();
else
this.Items = (this.Items.OrderBy(x => x.Name)).ToList();
}
else if (SortBy == "Description")
{
if (Direction == "Descending")
this.Items = (this.Items.OrderByDescending(x => x.Description)).ToList();
else
this.Items = (this.Items.OrderBy(x => x.Description)).ToList();
}
// I want to jump to the second page
this.Items = this.Items.Skip(26).ToList();
有一個更好的方法嗎? 所有的ToList
調用似乎都在消耗性能。 也許我錯了。
謝謝!
您可以將.ToList
調用.ToList
到最后一行,因為根據您的邏輯它始終會運行。 臨時邏輯基於IQueryable。 ToList是否具有重大影響,很大程度上取決於它是Linq2Objects還是Linq2SQL / Entitity Framework /某些其他數據庫ORM。 對於數據庫ORM,通常每個.ToList都會合並列表並導致執行數據庫查詢。 對於Linq2Objects而言,仍然存在性能成本,但是與數據庫調用所涉及的程度無關。
// itemsQuery will be of type IQueryable or IEnumerable depending on type of Items
var itemsQuery = model.Items.Where(x => x.Id > 0);
if (SortBy == "Description")
{
// we'll chain additional criteria or sorts to the IQueryable,
// and update the query reference by assigning over the previous itemsQuery variable
if (Direction == "Descending")
itemsQuery = itemsQuery.OrderByDescending(x => x.Description);
else
itemsQuery = itemsQuery.OrderBy(x => x.Description);
}
// I want to jump to the second page
this.Items = itemsQuery.Skip(26).ToList();
本質上,您是在動態構建查詢,但直到調用ToList時才真正運行查詢,這實際上將從表達式樹構建SQL查詢並執行.Where(...).OrderBy(...).Skip(26).ToList
的整個鏈式序列.Where(...).OrderBy(...).Skip(26).ToList
您完全正確,所有的ToList
調用都是一個主要問題。 如果基礎數據源代表數據庫查詢提供程序,它們不僅迫使所有工作在客戶端中完成,而且即使它本質上是LINQ對象查詢,您也不必要創建,填充和丟棄列表。 您還將刪除任何延遲執行的功能。 由於您實際上並沒有從這些電話中獲得任何收益,因此只需將其全部刪除即可。
接下來,您可以編寫一種方法來創建選擇器,這樣就無需為排序的每一列重復所有代碼:
public static Expression<Func<T, TResult>> CreateSelector<T, TResult>(
string memberName)
{
var param = Expression.Parameter(typeof(T));
var body = Expression.PropertyOrField(param, memberName);
return Expression.Lambda<Func<T, TResult>>(body, param);
}
這使您可以編寫:
IQueryable<Item> items = model.Items;
if (Direction == "Descending")
items = items.OrderByDescending(CreateSelector<Item, string>(SortBy));
else
items = items.OrderBy(CreateSelector<Item, string>(SortBy));
items = items.Skip(26);
如果您擁有的基礎數據源是IEnumerable
而不是IQueryable
,則只需更改Items
的類型並Compile
選擇器表達式即可。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.