繁体   English   中英

Linq to Entities有多对多选择:如何强制生成JOIN而不是subselect子句?

[英]Linq to Entities many to many selection: How to force the generation of a JOIN instead of a subselect clause?

在此输入图像描述

首先使用EF DB,我有两个具有多对多关系的实体(供应商,产品)。 实体框架不为关联表(SupplierProduct)创建实体,因为关联表仅包含强实体的主键。

我一直在向所有不提供给定产品的供应商提供以下查询:

var q1 = context.Suppliers.Where(s=>!s.Products.Any(p=>p.Id == 1));

生成的SQL使用类似于此的EXISTS依赖子查询:

SELECT *
FROM Suppliers s
WHERE NOT EXISTS
  (SELECT 1 
   FROM SupplierProduct sp WHERE sp.SupplierId = s.Id && sp.ProductId = 1)

是否可以使用Linq to Entities方法语法生成在关联表上使用连接的查询?

即:

SELECT DISTINCT s.*
FROM SupplierProduct sp
JOIN Supplier s ON s.Id = sp.SupplierId;
WHERE sp.ProductId != 1

更新

正如JoeEnos所指出的,我上面的查询并没有做同样的事情。 NOT EXISTS子查询可能是最好的方法。 如果我试图让所有的供应商是谁供应的产品? 我会将我的linq更改为实体查询稍微:

var q1 = context.Suppliers.Where(s => s.Products.Any(p=>p.Id == 1));

并且生成的SQL将是:

SELECT *
FROM Suppliers s
WHERE EXISTS
  (SELECT 1 
   FROM SupplierProduct sp WHERE sp.SupplierId = s.Id && sp.ProductId = 1)

哪个好,我得到了我想要的结果。 但是,如果我在这种情况下编写SQL,我通常会这样做:

SELECT s.*
FROM SupplierProduct sp
JOIN Supplier s ON s.Id = sp.SupplierId;
WHERE sp.ProductId = 1

可以将我的linq to entities查询更改为生成上述SQL吗?

要生成使用连接而不是EXISTS的SQL,当根据其与另一个实体的m:n关联选择实体时,可以使用SelectMany() 例如:

var q1 = context.Suppliers.Where(s => s.Products.Any(p=>p.Id == 1));

可以改写为:

var q1 = context.Products.Where(p => p.Id == 1).SelectMany(p => p.Suppliers);

你的两个查询做了很多不同的事情。 您的Any / EXISTS查询会获得根本没有产品1的供应商。 您的JOIN查询将获得所有非1的产品的供应商,无论他们是否也有产品1。

我认为你只需要一个JOINWHERE就可以做你正在寻找的东西 - 你可以使用IN子句来做,但我认为EXISTS查询是查找数据的最正确方法。

在任何情况下,关于实体框架的一个奇妙的事情是你不必担心生成什么 - 只要LINQ语句没问题,那么它将找到编写查询的最佳方式,你应该永远不要去看它。 当你进行分页和其他类似的事情时,尤其如此,LINQ很简单,但生成的SQL非常难看。

暂无
暂无

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

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