Linq to Entity有多个左外部联接
我试图理解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