使用join提高linq查询速度

时间:2013-11-04 17:08:27

标签: c# linq entity-framework join

我不习惯使用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 })

2 个答案:

答案 0 :(得分:2)

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

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

Include也生成SQL连接,但同时将所包含实体的所有列放在SELECT子句中。查询结果集用于实现所有包含的实体。当有许多Include时,这个结果会在宽度和长度方面令人难以置信。宽度,因为它选择所有包含的实体的所有列。在长度上,因为每个包含的子集合将结果集乘以其行数

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

答案 1 :(得分:1)

您正在使用的联接是内部联接,而不是左联接。您可以使用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),否则你获得的数据可能不是你期望的,如果它在时间之间变化创建查询以及执行查询的时间。

此外,对于许多包含我认为使用存储过程更容易。