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