这是一个LINQ查询,用于从DB中检索具有实体框架的数据7。有几个.Where(x => x.CollectedMaterial.OrderByDescending(y => y.Repeats).First()
。有没有办法优化此查询?是否需要这样做或EF优化它?
var bs = await db.Building.Include(x => x.CollectedMaterial)
.Where(x => x.MaterialIDLocked == BuildingDataLockType.LockedByBuildingInfoSource)
.Where(x => x.CollectedMaterial.Count > 0)
.Where(
x => x.CollectedMaterial.OrderByDescending(y => y.Repeats).First().Repeats >= firstRepeatsCount)
.Where(x => x.CollectedMaterial.OrderByDescending(y => y.Repeats).First().MaterialID != x.MaterialID)
.ToListAsync();
afaik您不应使用多个在其中删除列表的多个列表,而应将条件放入单个子句中。
编辑:是的
提示:尝试滤除查询本身中的所有数据,不要通过获取不必要的数据来过滤内存对象,甚至可能使用不必要的字段,您可以使用投影操作仅选择所需的字段。
这里的答案也这样说,我通常会选择余额b/w可读性和性能,您应该尝试评估需要提高性能的程度,还可以尝试Visual Studio Profiler,它具有内存,CPU样本等。<<
如果您是在GET方法中编写该代码,则可以在DBSET上使用Asnotracking方法,这将改善性能,因为实体框架不会使用默认情况下创建的跟踪对象对其进行跟踪。
使用dbcontext对象上的database.log属性记录生成的sql查询,并通过更改代码查看哪个查询似乎很复杂,这将帮助您。
您可以登录控制台应用程序context.Database.Log = Console.WriteLine;
您可以登录任何其他应用程序以调试或跟踪为context.Database.Log = message => Trace.WriteLine(message);
由于您正在使用IQueryable
,因此您可以根据需要将.Where()
条件链链,您所创建的只是一个表达树,稍后将进行评估。
实际上从DB检索数据(如示例ToList()
中)时,EF然后创建实际优化的SQL查询。
那么取决于..最好的做法是将SQL Profiler对您的DB运行并捕获并查看通过EF。
afaik,实体优化所有内容,直到实现实际的DB调用为止。在您的情况下,那是打电话给.ToListAsync
的时候。
编辑:查看此评论,看来您应该合并所有查询。不过,如果可以的话,请考虑使用变量叛逆。
关于优化,您可能需要合并
.Where( x => x.CollectedMaterial.OrderByDescending(y => y.Repeats).First().Repeats >= firstRepeatsCount)
.Where( x => x.CollectedMaterial.OrderByDescending(y => y.Repeats).First().MaterialID != x.MaterialID)
to
.Where( x => {
var firstRepeats = x.CollectedMaterial.OrderByDescending(y => y.Repeats).First().Repeats;
return ( firstRepeats.Repeats >= firstRepeatsCount &&
firstRepeats.MaterialID != x.MaterialID ) })
(未经测试)