[英]How to avoid OrderByDescending in query linq
我有 linq 查詢:
var ed = db.table
.GroupBy(x => x.Sn)
.Select(g => g.OrderByDescending(x => x.Date).FirstOrDefault());
我需要重寫此查詢以進行服務器端評估。
我的桌子:
Sn Value Data
150 180.3 01/06/2020
150 195.0 01/05/2020
149 13.3 01/06/2020
345 27.5 27/06/2013
....
.Select(g => g.OrderByDescending(x => x.Date).FirstOrDefault())
可能只是:
.Select(g => g.Max(x => x.Date))
解析器可能處理得更好
您可以嘗試使用Aggregate
var ed = db.table
.GroupBy(x => x.Sn)
.Select(x => x.Aggregate((max, cur) => max.Date > cur.Date ? max : cur));
這可能會幫助您了解更多如何使用 LINQ 到 select object 與最小或最大屬性值。
這取決於dt.Table
是否為 IQueryable。
通常 IQueryable 將由不同的進程執行,通常是數據庫管理系統。 在這種情況下,您必須使用 OrderBy 后跟 FirstOrDefault。
幸運的是,適當的數據庫管理系統已針對排序進行了極大優化。 如果您對排序的效率不滿意,並且您不經常更改表,請考慮在 DbContext.OnModelCreating 中添加一個額外的索引:
modelBuilder.Entity<Customer>()
.HasIndex(customer => customer.Name)
您的數據庫管理系統知道這個額外的索引,並且可以立即返回索引的最后一項所引用的元素。
每當您更改名稱或添加新客戶時,都必須重新創建索引。 因此,如果您經常更改客戶名稱,例如每秒 10 次,請不要這樣做。
如果dt.table
不是IQueryable,而是IEnumerable,OrderBy比較慢。 唉,沒有 Enumerable.Max 適合您,但您可以使用Enumerable.Aggregate的重載。
由於您確定每個組至少包含一個元素,因此您可以使用不帶 Seed 的重載:
var result = db.table.GroupBy(x => x.Sn)
.Aggregate( (maxItem, nextitem) =>(nextItem.Date > maxItem.Date) ?? nextItem : maxItem)
如果您經常使用它,請考慮創建一個擴展方法。 創建擴展方法非常容易。 請參閱揭秘的擴展方法
public static T MaxOrDefault<T, TProperty> MaxPropertyOrDefault(
this IEnumerable<T> source,
Func<TSource, TProperty> propertySelector)
{
return MaxPropertyOrDefault(source, propertySelector, null)
}
比較器重載:如果比較器等於 null,則使用默認比較器
public static T MaxOrDefault<T, TProperty> MaxPropertyOrDefault(
this IEnumerable<T> source,
Func<TSource, TProperty> propertySelector,
IComparer<TProperty) comparer)
{
// TODO: what to do if source == null?
// TODO: what to do if propertySelector == null?
if (comparer == null) comparer = Comparer<TProperty>.Default();
var enumerator = source.GetEnumerator();
if (!enumerator.MoveNext)
{
// empty source, return default:
return default(T);
}
else
{
TProperty maxPropertyValue = propertySelector(enumerator.Current);
T maxValue = enumerator.Current();
while (enumerator.MoveNext())
{
TProperty currentPropertyValue = propertySelector(enumerator.Current);
if (comparer.Compare(currentPropetyValue, maxPropertyValue) > 0)
{
maxPropertyValue = currentPropertyValue;
maxValue = enumerator.Current;
}
}
return maxValue;
}
}
用法:
var ed = db.table.GroupBy(x => x.Sn)
.Select(group => group.MaxOrDefault(groupElement => groupElement.Date);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.