1

我是 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但是已经通过键在数据库ProjectCommentsProjectFiles建立了关系,所以不确定我们可以通过再次设置关系来实现什么。

基本上,需要知道从性能角度来看哪种方法最好。需要注意的一件事是我正在排序ProjectComments并且只取最近的一个。我应该使用joinand的组合group by into吗?帮助将不胜感激。谢谢。

更新:

抱歉,如果我对我要做什么还不够清楚。基本上,在前端,我有一个网格,它显示带有最新项目评论的项目列表和与项目关联的所有文件的列表,因此用户可以单击这些链接并实际打开这些文档。所以我上面的查询是有效的,它确实在网格中显示了以下内容:

项目 ID(来自项目表) 状态(来自项目表) ExpiresOn(来自项目表) LatestComments(来自 ProjectComments 表的最新条目,其项目 ID 作为外键) ProjectFileIDs(来自 ProjectFiles 表的文件 ID 列表,其中项目 ID 作为外键- 我正在使用这些文件 ID 并创建链接,以便用户可以打开这些文件)。

所以一切正常,我已经设置好了,但是查询有点慢。现在我们的数据非常少(只有测试数据),但是一旦启动,我预计会有很多用户/数据,因此我想在它上线之前将这个查询优化到最好。所以,这里的目标是基本上优化。我很确定这不是最好的方法,因为这会创建嵌套选择。

4

2 回答 2

4

在 Entity Framework 中,您可以通过将对象返回为对象图而不是投影来显着提高查询的性能。Entity Framework 在优化除最复杂的 SQL 查询之外的所有查询方面都非常有效,并且可以利用延迟的“急切”加载与“延迟”加载(在实际访问之前不从数据库加载相关项目)。这个MSDN 参考是一个很好的起点。

就您的特定查询而言,您可以使用以下技术:

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 参考

性能注意事项

当您选择加载相关实体的模式时,请考虑每种方法的行为,即与数据源建立连接的数量和时间与返回的数据量和使用单个查询的复杂性。急切加载在单个查询中返回所有相关实体以及查询的实体。这意味着,虽然只有一个与数据源的连接,但在初始查询中会返回大量数据。此外,查询路径会导致更复杂的查询,因为在针对数据源执行的查询中需要额外的连接。

显式和延迟加载使您能够推迟对相关对象数据的请求,直到实际需要该数据。这产生了一个不太复杂的初始查询,它返回的总数据更少。但是,相关对象的每次连续加载都会连接到数据源并执行查询。在延迟加载的情况下,只要访问导航属性并且相关实体尚未加载,就会发生此连接。

于 2013-08-09T22:38:50.800 回答
0

如果Include在 ? 之前添加语句,是否会提高性能Select

例子:

var dProjects = Projects
    .Include(p => p.ProjectComments)
    .Include(p => p.ProjectFiles)

Include允许急切加载所有匹配的 ProjectComments 和 ProjectFiles。有关详细信息,请参阅加载相关实体。

于 2013-08-09T22:32:11.680 回答