简体   繁体   English

使用相关实体优化linq查询

[英]optimize linq query with related entities

i am new to linq, i started writing this query: 我是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>();

I already know this query will perform really slow because related entities like ProjectComments and ProjectFiles will create nested selects, though it works and gives me right results that i need. 我已经知道这个查询的执行速度会非常慢,因为像ProjectCommentsProjectFiles这样的相关实体会创建嵌套的选择,虽然它可以工作并给我正确的结果。

How can i optimize this query and get the same results? 如何优化此查询并获得相同的结果? One of my guesses would be using inner join but ProjectComments and ProjectFiles already has a relationship in database through keys, so not sure what we can achieve by setting the relationship again. 我的一个猜测是使用inner joinProjectCommentsProjectFiles已经通过键在数据库中建立了关系,所以不确定我们可以通过再次设置关系来实现。

Basically, need to know which is the best approach to take here from performance perspective. 基本上,需要从性能角度了解哪种方法最好。 One thing to note is i am sorting ProjectComments and only taking the most recent one. 有一点需要注意的是,我正在对ProjectComments排序,只采用最新的一个。 Should i be using combination of join and group by into ? 我应该使用joingroup by into吗? Help will be much appreciated. 将非常感谢帮助。 Thanks. 谢谢。

UPDATED: 更新:

Sorry, if i wasn't clear enough on what i am trying to do. 对不起,如果我不清楚我想做什么。 Basically, in front end, i have a grid, which shows list of projects with latest project comments and list of all the files associated to project, so users can click on those links and actually open those documents. 基本上,在前端,我有一个网格,它显示了包含最新项目注释的项目列表以及与项目关联的所有文件的列表,因此用户可以单击这些链接并实际打开这些文档。 So the query that i have above is working and it does show the following in the grid: 所以我上面的查询正在工作,它确实在网格中显示以下内容:

Project ID (From Project table) Status (From Project table) ExpiresOn (From Project table) LatestComments (latest entry from ProjectComments table which has project ID as foreign key) ProjectFileIDs (list of file ids from ProjectFiles table which has Project ID as foreign key - i am using those File IDs and creating links so users can open those files). 项目ID(来自项目表)状态(来自项目表)ExpiresOn(来自项目表)LatestComments(ProjectComments表中具有项目ID作为外键的最新条目)ProjectFileIDs(ProjectFiles表中具有项目ID作为外键的文件ID列表 - 我正在使用这些文件ID并创建链接,以便用户可以打开这些文件)。

So everything is working, i have it all setup, but the query is little slow. 所以一切正常,我已全部设置,但查询有点慢。 Right now we have very little data (only test data), but once this is launched, i am expecting lot of users/data and thus i want to optimize this query to the best, before it goes live. 现在我们只有很少的数据(只有测试数据),但一旦启动,我期待很多用户/数据,因此我希望在它出现之前优化这个查询。 So, the goal here is to basically optimize. 所以,这里的目标是基本上优化。 I am pretty sure this is not the best approach, because this will create nested selects. 我很确定这不是最好的方法,因为这将创建嵌套选择。

In Entity Framework, you can drastically improve the performance of the queries by returning the objects back as an object graph instead of a projection. 在实体框架中,您可以通过将对象作为对象图而不是投影返回来大幅提高查询的性能。 Entity Framework is extremely efficient at optimizing all but the most complex SQL queries, and can take advantage of deferred "Eager" loading vs. "Lazy" Loading (not loading related items from the db until they are actually accessed). 实体框架在优化除最复杂的SQL查询之外的所有查询方面非常有效,并且可以利用延迟的“Eager”加载与“延迟”加载(在实际访问它们之前不从数据库加载相关项目)。 This MSDN reference is a good place to start. 这个MSDN参考是一个很好的起点。

As far as your specific query is concerned, you could use this technique something like the following: 就您的特定查询而言,您可以使用以下类似的技术:

var dbProjects = yourContext.Projects
                    .Include(p => p.ProjectComments
                              .OrderByDescending(pc => pc.CreatedOn)
                              .Select(pc => pc.Comments)
                              .FirstOrDefault()
                            )
                    .Include(p => p.ProjectFileIDs)
                    .AsQueryable<Models.Project>();

note the .Include() being used to imply Eager Loading. 注意.Include()用于表示Eager Loading。

From the MDSN Reference on Loading Related Objects , 加载相关对象MDSN参考

Performance Considerations 性能注意事项

When you choose a pattern for loading related entities, consider the behavior of each approach with regard to the number and timing of connections made to the data source versus the amount of data returned by and the complexity of using a single query. 当您选择用于加载相关实体的模式时,请考虑每种方法在数据源连接的数量和时间与返回的数据量以及使用单个查询的复杂性方面的行为。 Eager loading returns all related entities together with the queried entities in a single query. 预先加载会在单个查询中将所有相关实体与查询实体一起返回。 This means that, while there is only one connection made to the data source, a larger amount of data is returned in the initial query. 这意味着,虽然只有一个连接到数据源,但在初始查询中返回的数据量较大。 Also, query paths result in a more complex query because of the additional joins that are required in the query that is executed against the data source. 此外,查询路径会导致更复杂的查询,因为在针对数据源执行的查询中需要额外的连接。

Explicit and lazy loading enables you to postpone the request for related object data until that data is actually needed. 显式和延迟加载使您可以推迟对相关对象数据的请求,直到实际需要该数据为止。 This yields a less complex initial query that returns less total data. 这会产生一个不太复杂的初始查询,返回较少的总数据。 However, each successive loading of a related object makes a connection to the data source and executes a query. 但是,相关对象的每次连续加载都会建立与数据源的连接并执行查询。 In the case of lazy loading, this connection occurs whenever a navigation property is accessed and the related entity is not already loaded. 在延迟加载的情况下,只要访问导航属性并且尚未加载相关实体,就会发生此连接。

Do you get any boost in performance if you add Include statements before the Select ? 如果在Select之前添加Include语句,您是否可以获得性能提升?

Example: 例:

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

Include allows all matching ProjectComments and ProjectFiles to be eagerly loaded. Include允许热切地加载所有匹配的ProjectComments和ProjectFiles。 See Loading Related Entities for more details. 有关更多详细信息,请参阅加载相关实体

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM