簡體   English   中英

在C#中有效使用LINQ

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM