我试图了解LINQ to Entity中的左外连接。例如,我有以下3个表:
公司,公司产品,产品
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个CompanyProduct记录与ProductID为14相关联。因此,SQL查询的结果是预期的3行,其中2行连接到CompanyProduct和Product,1个只有公司CompanyProduct和Product表中的表和空值。
那么如何在LINQ to Entity中编写相同类型的连接来实现类似的结果呢?
我尝试了一些不同的东西,但无法正确理解语法。
感谢。
答案 0 :(得分: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
答案 1 :(得分:6)
IT应该是这样的......
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
};
这就是我做的......
答案 2 :(得分: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
};
如果您想提供更多信息,请使用“添加评论”按钮,而不是创建其他答案。
答案 3 :(得分:2)
LEFT OUTER JOIN通过使用Entity Framework中的GroupJoin完成:
答案 4 :(得分: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
的所有记录。
答案 5 :(得分: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;
干杯!
答案 6 :(得分:0)
这个怎么样(你的实体设计师确实有公司和产品之间的多对多关系,不是吗?):
from s in db.Employees
where s.Product == null || s.Product.ProductID == 14
select s;
实体框架应该能够确定要使用的联接类型。