繁体   English   中英

如何避免查询 linq 中的 OrderByDescending

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM