设置:MS sql 2012,EF 6.1.3,Web Api 2和.NET 4.52
我目前正在使用具有此布局的表:
该表最终会变得非常大,所以当客户端获取这样的数据时我需要分页:
客户< ----> Web api 2< ---->实体框架< -----> MS SQL
所以..这是交易。我需要Email,Brand和Type_Id的每个独特组合的最新行(最高" createdAt") 将为每个电话设置品牌,以便我可以对其进行过滤。
我现在这样做的方式是这样的:
var result = _context.Permissions.Where(p => p.Brand == brandEnum)
.Include(p => p.Type)
.Include(p => p.UserType)
.OrderByDescending(o => o.CreatedAt)
.DistinctBy(p => new {p.Type, p.Email})
.Skip(pageSize*(page - 1))
.Take(pageSize);
public static class LinqExtensions {
public static IEnumerable<T> DistinctBy<T>(this IEnumerable<T> list, Func<T, object> propertySelector)
{
return list.GroupBy(propertySelector).Select(x => x.First());
}
}
好的,这就是问题所在。这是有效的,但是速度非常慢,因为它的实现方式是强制DB在每次调用时检索所有行,这最终会消除关于分页的整个想法。删除&#34; DistinctBy&#34;过滤器解决了速度问题,但现在也会返回较旧(不再有效)的数据。
所以我希望有人有一个有利于速度和功能的解决方案。
提前致谢。
答案 0 :(得分:0)
虽然我不确定它是否有更好的性能,但只能在您身边检查,这里有一些建议:
var result = _context.Permissions.Where(p => p.Brand == brandEnum)
.GroupBy(p => new {p.Type, p.Email})
.Select(g => g.OrderByDescending(o => o.CreatedAt)
.FirstOrDefault())
.OrderByDescending(o => o.CreatedAt)
.Skip(pageSize*(page - 1))
.Take(pageSize)
.Include(p => p.Type)
.Include(p => p.UserType);
答案 1 :(得分:0)
正如@KingKing建议的那样,您应该在扩展方法中按IEnumerable<T>
更改IQueryable<T>
类型:
public static IQueryable<T> DistinctBy<T>(this IQueryable<T> query, Func<T, object> propertySelector)
{
return query.GroupBy(propertySelector).Select(x => x.FirstOrDefault());
}
这就是我的查询方式:
var result = _context.Permissions.Where(p => p.Brand == brandEnum)
.Include(p => p.Type)
.Include(p => p.UserType)
.GroupBy((p => new {p.Type, p.Email})
.Select(x => x.OrderByDescending(o => o.CreatedAt).FirstOrDefault())
.Skip(pageSize*(page - 1))
.Take(pageSize);
如果您需要继续使用DistincBy
方法,我建议您移动该方法内的OrderByDescending
来调整群组:
public static IQueryable<T> DistinctBy<T>(this IQueryable<T> query, Func<T, object> propertySelector, IOrderedQueryable<TEntity>> orderBy = null)
{
var q=query.GroupBy(propertySelector);
if(orderBy!=null)
q= orderBy(q);
return q.Select(x => x.FirstOrDefault());
}
您的查询将是这样的:
var result = _context.Permissions.Where(p => p.Brand == brandEnum)
.Include(p => p.Type)
.Include(p => p.UserType)
.DistinctBy(p => new {p.Type, p.Email},q=>q.OrderByDescending(o => o.CreatedAt))
.Skip(pageSize*(page - 1))
.Take(pageSize);
在这种情况下,orderBy
参数是可选的。