我正在使用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()函数来尝试将查询包含在内。
答案 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();