Linq查询Where()与Date减法占用的时间过长

时间:2017-01-26 17:45:12

标签: c# linq

我正在使用C#和实体框架6。

我的数据库中有一个实体(Animal),它附有一个附加实体(Feeding)的列表。 Feeding实体具有与之关联的DateTime。

我的查询如下:

var sum = animal.Feedings.Where(f => (DateTimeOffset.Now.Date- f.DateTime.Date).Days == 1).Select(f => f.Amount).Sum()

我基本上想要从昨天起总喂食量的总和。但是如果我的Animal对象有非常大量的进给量(比如5000,这是预期的,甚至可能更高),这条线需要20多秒才能完成。

有没有办法重构这行代码以提高效率?

修改 它似乎是Feedings对象从动物对象中延迟加载。

var feedings = animal.Feedings

这条线现在需要花费过多的时间。动物对象最初是从AsQueryable()对象创建的,通过ID选择动物。

编辑#2 此逻辑位于Animal Repository中,无法访问DBContext,它只能访问Animal集合的IQueryable。我也无法访问EF的Include()函数来尝试将查询包含在内。

2 个答案:

答案 0 :(得分:3)

慢速部分正在加载Feedings集合。如果它已经加载,LINQ to Objects查询将运行得非常快。

如果您有权访问DbContext,而不是加载集合,您可以在数据库中执行查询,如下所示:

var date = new DateTimeOffset(DateTime.Today.AddDays(-1));
var sum = dbContext.Entry(animal).Collection(e => e.Feedings).Query()
    .Where(f => DbFunctions.TruncateTime(f.DateTime) == date)
    .Sum(f => f.Amount);

有权访问IQueryable<Animals>(如评论和更新中所述)也可以。而不是

dbContext.Entry(animal).Collection(e => e.Feedings).Query()

你会使用这样的东西

animals.Where(a => a.Id == animal.Id).SelectMany(a => a.Feedings)

其余的都是一样的。

答案 1 :(得分:2)

如果您有DateTime的索引,请尝试

 var startDate = DateTimeOffset.Now.AddDays(-1).Date;
 var endDate = DateTimeOffset.Now.Date;

 var sum = animal.Feedings
    .Where(f => (f.DateTime >= startDate && f.DateTime < endDate))
    .Select(f => f.Amount)
    .DefaultIfEmpty(0)   // don't throw an error if the query has no results
    .Sum();