我不习惯使用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 })
答案 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),否则你获得的数据可能不是你期望的,如果它在时间之间变化创建查询以及执行查询的时间。
此外,对于许多包含我认为使用存储过程更容易。