Linq to Entity有多个左外部联接

时间:2020-03-05 18:57:32  来源:igfitidea点击:

我试图理解LINQ到Entity中的左外部联接。例如,我有以下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的CompanyProduct记录。因此,SQL查询的结果是预期的3行,其中2行连接到CompanyProduct和Product,另外1行仅包含Company表和null在CompanyProduct和Product表中。

那么,我们如何在LINQ中编写与实体的联接以达到相似的结果呢?

我尝试了一些不同的操作,但是语法不正确。

谢谢。

解决方案

回答

请尝试这样的事情:

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;

干杯!

回答

那该怎么办(我们在实体设计器中公司与产品之间确实存在多对多关系,不是吗?):

from s in db.Employees
where s.Product == null || s.Product.ProductID == 14
select s;

实体框架应该能够弄清楚要使用的联接的类型。

回答

解决了!

最终输出:

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

这是场景

1数据库

--Company Table
CREATE TABLE [theCompany](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [value] [nvarchar](50) NULL,
 CONSTRAINT [PK_theCompany] PRIMARY KEY CLUSTERED 
( [id] ASC ) WITH (
    PAD_INDEX  = OFF, 
    STATISTICS_NORECOMPUTE  = OFF, 
    IGNORE_DUP_KEY = OFF, 
    ALLOW_ROW_LOCKS  = ON, 
    ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY];
GO

--Products Table
CREATE TABLE [theProduct](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [value] [nvarchar](50) NULL,
 CONSTRAINT [PK_theProduct] PRIMARY KEY CLUSTERED 
( [id] ASC
) WITH (    
    PAD_INDEX  = OFF, 
    STATISTICS_NORECOMPUTE  = OFF, 
    IGNORE_DUP_KEY = OFF, 
    ALLOW_ROW_LOCKS  = ON, 
    ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY];
GO

--CompanyProduct Table
CREATE TABLE [dbo].[CompanyProduct](
    [fk_company] [int] NOT NULL,
    [fk_product] [int] NOT NULL
) ON [PRIMARY];    
GO

ALTER TABLE [CompanyProduct]  WITH CHECK ADD CONSTRAINT
    [FK_CompanyProduct_theCompany] FOREIGN KEY([fk_company]) 
    REFERENCES [theCompany] ([id]);
GO

ALTER TABLE [dbo].[CompanyProduct] CHECK CONSTRAINT 
    [FK_CompanyProduct_theCompany];
GO

ALTER TABLE [CompanyProduct]  WITH CHECK ADD CONSTRAINT 
    [FK_CompanyProduct_theProduct] FOREIGN KEY([fk_product]) 
 REFERENCES [dbo].[theProduct] ([id]);
GO

ALTER TABLE [dbo].[CompanyProduct] CHECK CONSTRAINT 
    [FK_CompanyProduct_theProduct];

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中的实体

替代文字http://i478.photobucket.com/albums/rr148/KyleLanser/companyproduct.png
实体容器名称为" testEntities"(在模型"属性"窗口中看到)

4代码(最终!)

testEntities entity = new testEntities();

var theResultSet = from c in entity.theCompany
select new { company_id = c.id, product_id = c.theProduct.Select(e=>e) };

foreach(var oneCompany in theResultSet)
{
   Debug.WriteLine("theCompany.id: " + oneCompany.company_id);
    foreach(var allProducts in oneCompany.product_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;

或者

var query = Database.CompanySet
            .Where(c => c.Products.Any(p => p.ProductId == 14));

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"句子,则将获得" table1"的所有记录。

回答

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

http://msdn.microsoft.com/en-us/library/bb896266.aspx