我是linq的新手,我开始写这个查询:
var dProjects = Projects
.Select(p => new Models.Project {
ProjectID = p.ProjectID,
Status = p.Status,
ExpiresOn = p.ExpiresOn,
LatestComments = p.ProjectComments
.OrderByDescending(pc => pc.CreatedOn)
.Select(pc => pc.Comments)
.FirstOrDefault(),
ProjectFileIDs = p.ProjectFiles
.Select(pf => pf.BinaryFileID)
.AsQueryable()
})
.AsQueryable<Models.Project>();
我已经知道这个查询的执行速度会非常慢,因为像ProjectComments
和ProjectFiles
这样的相关实体会创建嵌套选择,虽然它可以正常工作,但却能为我提供正确的结果。
如何优化此查询并获得相同的结果?我的一个猜测是使用inner join
,但ProjectComments
和ProjectFiles
已经通过键在数据库中存在关系,所以不确定我们可以通过再次设置关系来实现。
基本上,需要从性能角度了解哪种方法最佳。有一点需要注意的是我正在排序ProjectComments
并且只采用最新的一个。我应该使用join
和group by into
的组合吗?将非常感谢帮助。感谢。
更新:
对不起,如果我对我要做的事情不够清楚。基本上,在前端,我有一个网格,它显示了包含最新项目注释的项目列表以及与项目关联的所有文件的列表,因此用户可以单击这些链接并实际打开这些文档。所以我上面的查询正在运行,它确实在网格中显示以下内容:
项目ID(来自项目表) 状态(来自项目表) ExpiresOn(来自项目表) LatestComments(项目ID为外键的ProjectComments表中的最新条目) ProjectFileIDs(ProjectFiles表中的文件ID列表,其项目ID为外键 - 我正在使用这些文件ID并创建链接,以便用户可以打开这些文件)。
所以一切正常,我已全部设置,但查询有点慢。现在我们只有很少的数据(只有测试数据),但一旦启动,我期待很多用户/数据,因此我希望在它出现之前优化这个查询。所以,这里的目标是基本上优化。我很确定这不是最好的方法,因为这将创建嵌套选择。
答案 0 :(得分:3)
在Entity Framework中,您可以通过将对象作为对象图而不是投影返回来大幅提高查询的性能。实体框架在优化除最复杂的SQL查询之外的所有查询方面非常有效,并且可以利用延迟的“Eager”加载与“延迟”加载(在实际访问它们之前不从数据库加载相关项目)。这个MSDN reference是一个很好的起点。
就您的特定查询而言,您可以使用以下技术:
var dbProjects = yourContext.Projects
.Include(p => p.ProjectComments
.OrderByDescending(pc => pc.CreatedOn)
.Select(pc => pc.Comments)
.FirstOrDefault()
)
.Include(p => p.ProjectFileIDs)
.AsQueryable<Models.Project>();
注意.Include()
用于表示预先加载。
来自MDSN Reference on Loading Related Objects,
效果注意事项
当您选择用于加载相关实体的模式时,请考虑每种方法在数据源连接的数量和时间与返回的数据量以及使用单个查询的复杂性方面的行为。预先加载会在单个查询中将所有相关实体与查询实体一起返回。这意味着,虽然只有一个连接到数据源,但在初始查询中返回的数据量较大。此外,查询路径会导致更复杂的查询,因为在针对数据源执行的查询中需要额外的连接。
显式和延迟加载使您可以推迟对相关对象数据的请求,直到实际需要该数据为止。这会产生一个不太复杂的初始查询,返回较少的总数据。但是,相关对象的每次连续加载都会建立与数据源的连接并执行查询。在延迟加载的情况下,只要访问导航属性并且尚未加载相关实体,就会发生此连接。
答案 1 :(得分:0)
如果您在Include
之前添加Select
语句,会不会提升效果?
示例:
var dProjects = Projects
.Include(p => p.ProjectComments)
.Include(p => p.ProjectFiles)
Include
允许所有匹配的ProjectComments和ProjectFiles 急切地加载。有关详细信息,请参阅Loading Related Entities。