LINQ to Entityの左外部結合を理解しようとしています。たとえば、次の3つのテーブルがあります。
会社、会社製品、製品
CompanyProductは、2つの親テーブル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テーブルとnullのみを持っています。 CompanyProductテーブルとProductテーブル。
では、同様の結果を達成するために、LINQ to Entityで同じ種類の結合をどのように記述しますか?
いくつかのことを試しましたが、構文を正しく取得できません。
ありがとう。
解決しました!
最終出力:
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
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
};
これは私がやった方法です...
Entity Frameworkを使用して、CompanyからProductへの多対多のマッピングを設定します。これは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
};
別の回答を作成するのではなく、詳細を提供する場合は、[コメントを追加]ボタンを使用してください。
LEFT OUTER JOINは、Entity FrameworkのGroupJoinを使用して行われます。
通常のグループ結合は、左外部結合を表します。これを試して:
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
のすべてのレコードが取得されます。
次のようなものを試してください:
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;
Entity Frameworkは、使用する結合のタイプを把握できる必要があります。