20

我试图了解 LINQ to Entity 中的左外连接。例如,我有以下 3 个表:

公司、公司产品、产品

CompanyProduct 链接到其两个父表 Company 和 Product。

无论给定产品的 CompanyProduct 是否存在,我都想返回所有 Company 记录和关联的 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 条 CompanyProduct 记录与 ProductID 14 相关联。因此,SQL 查询的结果是预期的 3 行,其中 2 行连接到 CompanyProduct 和 Product,1 行仅包含 Company 表和空值在 CompanyProduct 和 Product 表中。

那么如何在 LINQ to Entity 中编写相同类型的连接来获得类似的结果呢?

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

谢谢。

4

7 回答 7

16

解决了!

最终输出:

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

alt text 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  
于 2008-10-06T18:39:27.007 回答
6

它应该是这样的......

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


    };

我就是这样做的......

于 2011-03-18T12:05:15.020 回答
5

您将希望使用实体框架来设置从公司到产品的多对多映射。这将使用 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
            };

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

于 2009-10-02T20:30:47.640 回答
2

LEFT OUTER JOIN 是通过使用实体框架中的 GroupJoin 完成的:

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

于 2010-10-29T18:18:57.567 回答
1

普通组连接表示左外连接。尝试这个:

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

于 2010-08-20T09:29:06.440 回答
0

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

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

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

于 2008-10-06T18:08:37.693 回答
0

请尝试这样的事情:

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;

干杯!

于 2008-09-17T00:43:38.847 回答