2008-09-16 27 views
20

LINQ to Entityの左外部結合を理解しようとしています。 CompanyProductは、その2つの親テーブル、当社及び製品にリンクされている複数の左外部結合を持つエンティティへのLinq

会社、CompanyProduct、製品

:たとえば、私は、次の3つのテーブルを持っています。

私は、すべての会社の記録と、それに関連するCompanyProductを返したいと思います。

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 

私のデータベースはの商品コードとassocaited 3社、および2つのCompanyProductレコードを持っている14ので、SQLクエリの結果は次のとおりのTransact SQLで、私は次のように左外部結合を使用して、当社のテーブルから行くだろう期待される3行、そのうちの2つはCompanyProductとProductに接続され、1はCompanyProductとProductテーブルにCompany表とnullを単純に持ちます。

同様の結果を得るには、LINQ to Entityでどのように同じ種類の結合を記述しますか?

私はいくつかのことを試みましたが、正しい構文を取得できません。

ありがとうございました。

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; 

乾杯:

答えて

0

このような何かを試してみてください!

0

この1(あなたは、あなたのエンティティデザイナーで会社名および製品間の多対多の関係を持っていないのですか?)についてはどう:

Entity Frameworkのは把握することができるはず
from s in db.Employees 
where s.Product == null || s.Product.ProductID == 14 
select s; 

使用する結合のタイプ

16

解決済み!

最終出力: - データベース

--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]; 

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

ここでは、シナリオ

1であります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

'.Select(e => e)'はノーオペレーションであり、削除することができます。もちろん、あなたがIDだけを使っているなら、 '.Select(e => e.id)'と言ってみてはいかがですか? – StriplingWarrior

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 
      }; 

「コメントを追加」ボタンを使用してください。

+0

私はあなたがそれを解決したとは思わない、あなたは回避策を見つけた。 – theKing

+0

@theKing:私は違います。 OPは、 "類似の結果を得るために、LINQにEntityと同じ種類の結合をどのように書くのですか? LINQ to Entities *でこれを行う正しい方法は、多対多の関係を確立し、関係プロパティを介して関連するエンティティにアクセスすることです。 OPの最終的なソリューションは同じ戦略を使用していました。質問のどの面を解決できなかったのですか? – StriplingWarrior

+0

彼はまた、同様に回避策を見つけました。ソリューションはこのリンクにありますhttp://msdn.microsoft.com/en-us/library/bb896266.aspx – theKing

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() }; 

の例では、あなたのtable2への参照を持っていないtable1からすべてのレコードを与えること。 where文を省略すると、すべてのレコードがtable1になります。

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 


    }; 

は、これは私がやった方法です。.. ..

関連する問題