2008-09-16 14 views
20

J'essaie de comprendre les jointures externes gauche dans LINQ à Entity. Par exemple, j'ai les 3 tableaux suivants:Linq to Entity avec plusieurs jointures externes à gauche

Company, CompanyProduct, Produit

Le CompanyProduct est lié à ses deux tables parent, société et du produit.

Je souhaite retourner tous les enregistrements de la société et le CompanyProduct associé, que le produit de la société existe ou non pour un produit donné. Dans Transact SQL je passer de la table de l'entreprise à l'aide extérieure gauche rejoint comme suit:

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 

Ma base de données dispose de 3 entreprises et 2 records CompanyProduct assocaited avec le ProductID 14. Ainsi, les résultats de la requête SQL sont les 3 lignes attendues, dont 2 sont connectées à un CompanyProduct et Product et 1 qui a simplement la table Company et null dans les tables CompanyProduct et Product.

Alors, comment écrivez-vous le même type de jointure dans LINQ to Entity pour obtenir un résultat similaire?

J'ai essayé plusieurs choses mais je n'arrive pas à obtenir la syntaxe correcte.

Merci.

Répondre

0

S'il vous plaît essayer quelque chose comme ceci:

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; 

Cheers!

0

Qu'en est celui-ci (vous avez un grand nombre à plusieurs entre l'entreprise et produit dans votre Designer entité, non?):

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

Entity Framework devrait être en mesure de comprendre le type de jointure à utiliser.

16

Résolu!

Sortie finale:

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

Voici le scénario

1 - La base de données

--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 - Les données

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 - L'entité VS.NET 2008

alt text http://i478.photobucket.com/albums/rr148/KyleLanser/companyproduct.png
Le nom de conteneur entité est 'testEntities' (comme on le voit dans le modèle fenêtre Propriétés)

4 - Le code (FINALEMENT!)

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 - La sortie finale

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

'.Select (e => e)' est un no-op, et peut être retiré. Bien sûr, si vous n'utilisez que l'ID, pourquoi ne pas dire '.Select (e => e.id)'? – StriplingWarrior

5

Vous voulez utiliser Entity Framework pour mettre en place un grand nombre à plusieurs cartographie de la société au produit. Cela utilisera la table CompanyProduct, mais rendra inutile la définition d'une entité CompanyProduct dans votre modèle d'entité. Une fois que vous avez fait cela, la requête sera très simple, et cela dépendra de vos préférences personnelles et de la façon dont vous voulez représenter les données. Par exemple, si vous voulez juste toutes les entreprises qui ont un produit donné, on pourrait dire:

var query = from p in Database.ProductSet 
      where p.ProductId == 14 
      from c in p.Companies 
      select c; 

ou

var query = Database.CompanySet 
      .Where(c => c.Products.Any(p => p.ProductId == 14)); 

Votre requête SQL renvoie les informations produit, ainsi que les entreprises. Si c'est ce que vous allez pour, vous pouvez essayer:

var query = from p in Database.ProductSet 
      where p.ProductId == 14 
      select new 
      { 
       Product = p, 
       Companies = p.Companies 
      }; 

S'il vous plaît utiliser le bouton « Ajouter un commentaire » si vous souhaitez fournir plus d'informations, plutôt que de créer une autre réponse.

+0

Je ne pense pas que vous l'avez résolu, vous avez trouvé une solution de contournement. – theKing

+0

@theKing: Je ne suis pas d'accord. L'OP a demandé, "Alors, comment écrivez-vous le même type de jointure dans LINQ à Entity pour obtenir un résultat similaire?" La façon correcte de le faire dans LINQ to Entities * est d'établir une relation many-to-many et d'accéder aux entités associées via la propriété relationship. Vous voyez que la solution finale du PO utilisait la même stratégie. Quel aspect de la question ai-je échoué à résoudre? – StriplingWarrior

+0

Il a également trouvé un travail autour aussi. La solution est dans ce lien http://msdn.microsoft.com/en-us/library/bb896266.aspx qui est fourni par Mitch ci-dessous – theKing

1

La jointure de groupe normal représente une jointure externe gauche. Essayez ceci:

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

Cet exemple vous donne tous les enregistrements de table1 qui ne sont pas une référence à table2. Si vous omettez la phrase where, vous obtenez tous les enregistrements de table1.

6

IT devrait être quelque chose comme ça ....

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 


    }; 

Voilà comment je l'ai fait ..