Join Linq到具有多个左外部联接的实体

Join Linq到具有多个左外部联接的实体,join,linq-to-entities,outer-join,Join,Linq To Entities,Outer Join,我试图理解LINQ到实体中的左外连接。例如,我有以下3个表: 公司,公司产品,产品 CompanyProduct链接到它的两个父表Company和Product 我想返回所有公司记录和关联的CompanyProduct,无论给定产品的CompanyProduct是否存在。在Transact-SQL中,我将使用左外部联接从Company表开始,如下所示: SELECT * FROM Company AS C LEFT OUTER JOIN CompanyProduct AS CP ON C.Co

我试图理解LINQ到实体中的左外连接。例如,我有以下3个表:

公司,公司产品,产品

CompanyProduct链接到它的两个父表Company和Product

我想返回所有公司记录和关联的CompanyProduct,无论给定产品的CompanyProduct是否存在。在Transact-SQL中,我将使用左外部联接从Company表开始,如下所示:

SELECT * FROM Company AS C
LEFT OUTER JOIN  CompanyProduct AS CP ON C.CompanyID=CP.CompanyID
LEFT OUTER JOIN  Product AS P ON CP.ProductID=P.ProductID 
WHERE      P.ProductID = 14 OR P.ProductID IS NULL
我的数据库有3个公司,2个公司产品记录与ProductID 14关联。因此,SQL查询的结果是预期的3行,其中2行连接到CompanyProduct和Product,1行在CompanyProduct和Product表中仅包含Company表和null

那么,如何在LINQ to实体中编写相同类型的连接以获得类似的结果呢

我尝试了一些不同的方法,但语法不正确


谢谢。

请尝试以下内容:

from s in db.Employees
join e in db.Employees on s.ReportsTo equals e.EmployeeId
join er in EmployeeRoles on s.EmployeeId equals er.EmployeeId
join r in Roles on er.RoleId equals r.RoleId
where e.EmployeeId == employeeId &&
er.Status == (int)DocumentStatus.Draft
select s;
干杯

这个呢(在实体设计器中,公司和产品之间确实存在多对多关系,不是吗?)

实体框架应该能够确定要使用的连接类型。

解决了它

最终输出:

theCompany.id: 1  
theProduct.id: 14  
theCompany.id: 2  
theProduct.id: 14  
theCompany.id: 3  

以下是场景

1-数据库

——公司表
创建表[公司](
[id][int]标识(1,1)不为空,
[value][nvarchar](50)空,
约束[PK_the company]主键群集
([id]ASC)带有(
PAD_索引=关闭,
统计信息\u NORECOMPUTE=OFF,
忽略重复键=关闭,
允许\u行\u锁=打开,
在[主]上允许页面锁定
)关于[初级];
去
--产品表
创建表[产品](
[id][int]标识(1,1)不为空,
[value][nvarchar](50)空,
约束[PK_theProduct]主键群集
([id]ASC
)与(
PAD_索引=关闭,
统计信息\u NORECOMPUTE=OFF,
忽略重复键=关闭,
允许\u行\u锁=打开,
在[主]上允许页面锁定
)关于[初级];
去
--公司产品表
创建表[dbo]。[CompanyProduct](
[fk_company][int]不为空,
[fk_product][int]不为空
)关于[初级];
去
使用CHECK ADD约束更改表[CompanyProduct]
[FK_公司产品公司]外键([FK_公司])
参考文献[公司]([id]);
去
ALTER TABLE[dbo].[CompanyProduct]检查约束
[FK_Company Product_the Company];
去
使用CHECK ADD约束更改表[CompanyProduct]
[FK_公司产品产品]外键([FK_产品])
参考文献[dbo]。[theProduct]([id]);
去
ALTER TABLE[dbo].[CompanyProduct]检查约束
[FK_公司产品];
2-数据

SELECT [id] ,[value] FROM theCompany
id          value
----------- --------------------------------------------------
1           company1
2           company2
3           company3

SELECT [id] ,[value]  FROM theProduct
id          value
----------- --------------------------------------------------
14          Product 1


SELECT [fk_company],[fk_product] FROM CompanyProduct;
fk_company  fk_product
----------- -----------
1           14
2           14
3-VS.NET 2008中的实体


实体容器名称为“testEntities”(如模型属性窗口中所示)

4-代码(最后!)

testEntities entity=newtestentities();
var theResultSet=来自entity.theCompany中的c
选择新的{company_id=c.id,product_id=c.theProduct.select(e=>e)};
foreach(结果集中的一家公司)
{
Debug.WriteLine(“company.id:+oneCompany.company\u id”);
foreach(var一家公司的所有产品。产品id)
{
Debug.WriteLine(“theProduct.id:+allProducts.id”);
}
}
5-最终输出

theCompany.id: 1  
theProduct.id: 14  
theCompany.id: 2  
theProduct.id: 14  
theCompany.id: 3  

您需要使用实体框架来设置从公司到产品的多对多映射。这将使用CompanyProduct表,但不需要在实体模型中设置CompanyProduct实体。完成后,查询将非常简单,它将取决于个人偏好以及您希望如何表示数据。例如,如果您只想让所有拥有给定产品的公司,您可以说:

var query = from p in Database.ProductSet
            where p.ProductId == 14
            from c in p.Companies
            select c;

SQL查询将返回产品信息以及公司信息。如果这就是你想要的,你可以尝试:

var query = from p in Database.ProductSet
            where p.ProductId == 14
            select new
            {
                Product = p,
                Companies = p.Companies
            };

如果您想提供更多信息,而不是创建另一个答案,请使用“添加注释”按钮。

正常组联接表示左外联接。试试这个:

var list = from a in _datasource.table1
           join b in _datasource.table2
           on a.id equals b.table1.id
           into ab
           where ab.Count()==0
           select new { table1 = a, 
                        table2Count = ab.Count() };
该示例提供了
table1
中所有未引用
table2
的记录。
如果省略
where
语句,您将获得
表1的所有记录

左侧外部联接通过使用实体框架中的GroupJoin完成:


应该是这样的

var query = from t1 in db.table1
    join t2 in db.table2
    on t1.Field1 equals t2.field1 into T1andT2
    from t2Join in T1andT2.DefaultIfEmpty()


    join t3 in db.table3
    on t2Join.Field2 equals t3.Field3 into T2andT3
    from t3Join in T2andT3.DefaultIfEmpty()
    where t1.someField = "Some value" 
    select 
    {
        t2Join.FieldXXX
        t3Join.FieldYYY


    };

我就是这样做的……

。选择(e=>e)
是一个不可操作的选项,可以删除。当然,如果你只使用ID,为什么不说
。选择(e=>e.ID)
?@国王:我不同意。OP问:“那么,如何在LINQ to Entity中编写相同类型的联接以获得类似的结果呢?”在LINQ to Entity中这样做的正确方法是建立多对多关系,并通过关系属性访问相关实体。您可以看到OP的最终解决方案使用了相同的策略。我没能解决问题的哪一方面?他也找到了解决办法。解决方案就在这个由米奇提供的链接中below@theKing:我不同意。在使用实体框架时,“组联接”是一种变通方法,当您无法设置上下文以正确建模数据的关系时,可以使用它。在不必要时使用它会产生过多且容易出错的代码。OP找到了“正确的方法”,而不是解决问题。我想我们需要学会不同意。我想知道为什么微软和所有你能在亚马逊上找到的LINQ书籍都推荐使用GroupJoin?我想他们一定已经适应了这种变通办法too@theKing:“LINQ书籍”并不是关于实体框架的。Microsoft和所有LINQ to Entities书籍和文章都推荐多对多映射。这就是为什么他们做了这么大的一个d
var list = from a in _datasource.table1
           join b in _datasource.table2
           on a.id equals b.table1.id
           into ab
           where ab.Count()==0
           select new { table1 = a, 
                        table2Count = ab.Count() };
var query = from t1 in db.table1
    join t2 in db.table2
    on t1.Field1 equals t2.field1 into T1andT2
    from t2Join in T1andT2.DefaultIfEmpty()


    join t3 in db.table3
    on t2Join.Field2 equals t3.Field3 into T2andT3
    from t3Join in T2andT3.DefaultIfEmpty()
    where t1.someField = "Some value" 
    select 
    {
        t2Join.FieldXXX
        t3Join.FieldYYY


    };