【问题标题】:Improve linq query speed using join使用 join 提高 linq 查询速度
【发布时间】:2013-11-04 17:08:27
【问题描述】:

我不使用 linq。我使用 EF 4.0。我总是使用 lambda 表达式来获取我的数据,如下所示:

List<User> users = db.Users
                        .Include(u => u.Licences)
                        .Include(u => u.Licences.Select(l => l.LicenceProducts.Select(lp => lp.Product)))
                        .Include(u => u.UserAddress)
                        .Include(u => u.Contact)
                        .Include(u => u.User2)
                        .Include(u => u.SupportProducts)
                        .Where(u => u.Type != (int)UserType.Admin)
                        .OrderBy(u => u.Name)
                        .ToList();

不幸的是,执行需要很长时间。所以,我想通过使用左连接来改变它,但我没有正确理解连接在 Linq 中的工作方式。

这是我尝试过的:

users = from user in db.Users
        join licence in db.Licences on user.UserID equals licence.UserID
        join licenceProduct in db.LicenceProducts on licence.LicenceID equals licenceProduct.LicenceID...;

返回的类型,和之前的不一样(List)

我也试过了,但我有同样的问题

users = db.Users
    .Join(db.Licences, lic => lic.UserID, user => user.UserID, (user, lic) => new { user, lic })

【问题讨论】:

  • 确保您的数据库中有索引。
  • 我的数据库中有索引。我只想知道如何使用连接。我相信它会加快查询速度。

标签: c# linq entity-framework join


【解决方案1】:

联接的作用与Include 不同。 Includes 告诉 EF 从主查询中的实体填充关联的导航属性。但是,联接仅执行 SQL 联接,但不填充任何内容。

如果要过滤子对象或父对象中的属性,通常会使用连接。像join c in Contacts ... where c.Name == "..." - 这只会返回Users 而不填充任何联系人。 SQL SELECT 子句仅包含用户列。 (好吧,假设您只选择不同的用户)。

Includes 也产生 SQL 连接,但同时将包含的实体的所有列放在 SELECT 子句中。查询结果集用于具体化所有包含的实体。当Includes 有很多时,这个结果会在宽度和长度上爆炸得难以置信。在宽度上,因为它选择了所有包含实体的所有列。在长度上,因为每个包含的子集合将结果集乘以其行数。

因此建议不要超过三个Includes。所以我认为你必须重新考虑你真正需要的Includes 的数量。在单独的查询中加载关联实体可能效率更高。

【讨论】:

  • 谢谢你的回答!我现在明白了 Include 和 d join 之间的区别。正如您所建议的,我怎样才能执行所有 Includes 而不删除它们。我可以将它们放在同一个对象中吗(List&lt;User&gt; users)。事实上,有没有办法只选择列而不是跟踪整个对象。
  • 如果你只想选择一些列,也就是 projection,你可以使用 joins 和 select new { ... } (但是你没有和用户一样) .您可以通过将相关实体加载到上下文中来模仿@​​987654335@s。 EF 将通过relationship fixup 将它们粘合在一起。详情请见this
【解决方案2】:

您使用的连接是内连接,而不是左连接。您可以使用DefaultIfEmpty() 将它们变成左连接,如下所述:http://msdn.microsoft.com/en-us/library/vstudio/bb397895.aspx

另外,请注意,使用 linq 您正在创建一个查询,而不是一个列表。只有在需要检索结果时才会执行查询。您可以致电ToList() 来执行此操作。一般来说,如果您使用 LINQ 检索数据,请务必阅读有关延迟执行的信息(此处有很好的解释:http://blogs.msdn.com/b/charlie/archive/2007/12/09/deferred-execution.aspx),否则如果在查询时间之间发生变化,您获得的数据可能不是您所期望的创建和执行的时间。

另外,我认为使用存储过程更容易。

【讨论】:

  • 我尝试使用 toList(),它不起作用我得到这个 cannot implicitly convert type 'system.linq.iqueryable anonymous type' to 'System.Collections.Generic.List&lt;PAService.PartnerEDM.User&gt;#1'
  • 我不想在这种情况下使用 store proc。我认为使用连接会加快执行速度。
  • 而且我已经阅读了这两个主题。我在 linqpad 上测试它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-09-27
  • 1970-01-01
  • 1970-01-01
  • 2017-01-20
  • 2012-03-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多