为什么要使用LINQ加入简单的一对多关系?

时间:2021-12-23 20:52:39

I've been using LINQ to SQL and Entity Framework for a few years and I've always mapped my database relationships to generate the relevant navigation properties. And I always use the navigation properties.

我已经使用LINQ to SQL和Entity Framework几年了,我总是映射我的数据库关系以生成相关的导航属性。我总是使用导航属性。

Am I missing something?

我错过了什么吗?

If I have a Category->Products one-many type relationship, I would use

如果我有一个Category-> Products one-many类型的关系,我会用

var redProducts = context.Category.Single(c => c.Name = "red").Products;

I regularly see people doing manual joins, all over this site, in projects online, and various other websites.

我经常看到人们在这个网站,在线项目和各种其他网站上进行手动连接。

var employer = from category in context.Categories
               join product in context.Products
               on category.CategoryId equals product.CategoryId
               where category.Name == "red"
               select product;

So - why? What are the benefits of using this Join syntax?

所以为什么?使用此Join语法有什么好处?

3 个解决方案

#1


9  

It's usually a mistake.

这通常是个错误。

@George is correct that your two examples are functionally different in a way which has nothing to do with join vs non-join, however. But you could just as easily write:

@George是正确的,你的两个例子在功能上是不同的,但是与join和non-join无关。但你可以轻松地写:

var redProducts = context.Category
                         .Where(c => c.Name == "red")
                         .SelectMany(c => c.Products);

...which is functionally identical (but superior from a readability and maintainability POV) to your join example.

...功能相同(但可读性和可维护性POV优于您的加入示例)。

#2


4  

It might result from porting the old code to linq2sql.

将旧代码移植到linq2sql可能会导致这种情况。

However, the two code snippets are not functionally equal.

但是,这两个代码片段在功能上并不相同。

Single will throw exception, while join yields an empty collection in case of missing record.

Single将抛出异常,而join会在缺少记录时产生空集合。

So, an equal code without using joins would be:

因此,不使用连接的相同代码将是:

from c in context.Categories where c.Name == "red" from p in c.Products select p;

or

要么

context.Categories.Where(c=>c.Name == "red").SelectMany(c=>c.Products);

#3


3  

Joins are probably more common for people coming from the Relational mindset rather than the object oriented one. If you think about your problem space from a object orientented perspective, it is much more natural to work with relationships where you can dot through the navigation: Employee.Customers.Orders.OrderItems.OrderItem than to deal with a bunch of joins. The original ADO.vNext whitepaper did a good job of discussing the advantages of using the model and associations rather than joins for dealing with your conceptual models. Unfortunately, I can't find that document at this point.

对于来自Relational心态而不是面向对象的人来说,联接可能更常见。如果从对象取向的角度考虑问题空间,那么使用可以点击导航的关系更自然:Employee.Customers.Orders.OrderItems.OrderItem比处理一堆连接更为自然。最初的ADO.vNext白皮书很好地讨论了使用模型和关联而不是连接来处理概念模型的优势。不幸的是,我现在找不到那份文件。

For me, joins are best used when you don't have natural associations between entities. For example, if you are trying to join items on unnatural keys (i.e. joining on the Customer.State and Shipping.State) you should use the join syntax (or SelectMany) rather than creating associations between your entities in this case.

对我来说,当实体之间没有自然关联时,最好使用连接。例如,如果您尝试连接非自然键上的项目(即加入Customer.State和Shipping.State),则应使用连接语法(或SelectMany),而不是在这种情况下创建实体之间的关联。

One thing to be aware of is that the join syntax and using associations can cause differences in the kind of joins that are generated by the provider. Typically a Join translates into an Inner join and excludes items where there is no match on both sides of the join. To perform an (left) outer join, you use the DefaultIfEmpty extension.

需要注意的一点是,连接语法和使用关联可能会导致提供程序生成的连接类型存在差异。通常,Join转换为内部联接,并排除联接两侧不匹配的项目。要执行(左)外部联接,请使用DefaultIfEmpty扩展名。

Navigating through associations in a 1-0..* relationship on the other hand typically translate into Right Outer joins because the child collection could legitimately be empty and you would want to include the parent even if the child didn't exist. You would use !Any() to trap for cases were there aren't child records.

另一方面,通过1-0 .. *关系中的关联导航通常会转换为右外连接,因为子集合可能合法地为空,并且即使子项不存在,您也希望包含父项。如果没有子记录,您可以使用!Any()陷阱。

#1


9  

It's usually a mistake.

这通常是个错误。

@George is correct that your two examples are functionally different in a way which has nothing to do with join vs non-join, however. But you could just as easily write:

@George是正确的,你的两个例子在功能上是不同的,但是与join和non-join无关。但你可以轻松地写:

var redProducts = context.Category
                         .Where(c => c.Name == "red")
                         .SelectMany(c => c.Products);

...which is functionally identical (but superior from a readability and maintainability POV) to your join example.

...功能相同(但可读性和可维护性POV优于您的加入示例)。

#2


4  

It might result from porting the old code to linq2sql.

将旧代码移植到linq2sql可能会导致这种情况。

However, the two code snippets are not functionally equal.

但是,这两个代码片段在功能上并不相同。

Single will throw exception, while join yields an empty collection in case of missing record.

Single将抛出异常,而join会在缺少记录时产生空集合。

So, an equal code without using joins would be:

因此,不使用连接的相同代码将是:

from c in context.Categories where c.Name == "red" from p in c.Products select p;

or

要么

context.Categories.Where(c=>c.Name == "red").SelectMany(c=>c.Products);

#3


3  

Joins are probably more common for people coming from the Relational mindset rather than the object oriented one. If you think about your problem space from a object orientented perspective, it is much more natural to work with relationships where you can dot through the navigation: Employee.Customers.Orders.OrderItems.OrderItem than to deal with a bunch of joins. The original ADO.vNext whitepaper did a good job of discussing the advantages of using the model and associations rather than joins for dealing with your conceptual models. Unfortunately, I can't find that document at this point.

对于来自Relational心态而不是面向对象的人来说,联接可能更常见。如果从对象取向的角度考虑问题空间,那么使用可以点击导航的关系更自然:Employee.Customers.Orders.OrderItems.OrderItem比处理一堆连接更为自然。最初的ADO.vNext白皮书很好地讨论了使用模型和关联而不是连接来处理概念模型的优势。不幸的是,我现在找不到那份文件。

For me, joins are best used when you don't have natural associations between entities. For example, if you are trying to join items on unnatural keys (i.e. joining on the Customer.State and Shipping.State) you should use the join syntax (or SelectMany) rather than creating associations between your entities in this case.

对我来说,当实体之间没有自然关联时,最好使用连接。例如,如果您尝试连接非自然键上的项目(即加入Customer.State和Shipping.State),则应使用连接语法(或SelectMany),而不是在这种情况下创建实体之间的关联。

One thing to be aware of is that the join syntax and using associations can cause differences in the kind of joins that are generated by the provider. Typically a Join translates into an Inner join and excludes items where there is no match on both sides of the join. To perform an (left) outer join, you use the DefaultIfEmpty extension.

需要注意的一点是,连接语法和使用关联可能会导致提供程序生成的连接类型存在差异。通常,Join转换为内部联接,并排除联接两侧不匹配的项目。要执行(左)外部联接,请使用DefaultIfEmpty扩展名。

Navigating through associations in a 1-0..* relationship on the other hand typically translate into Right Outer joins because the child collection could legitimately be empty and you would want to include the parent even if the child didn't exist. You would use !Any() to trap for cases were there aren't child records.

另一方面,通过1-0 .. *关系中的关联导航通常会转换为右外连接,因为子集合可能合法地为空,并且即使子项不存在,您也希望包含父项。如果没有子记录,您可以使用!Any()陷阱。