web-dev-qa-db-fra.com

LINQ to Entity: conditions de jointure multiples

Il existe de nombreux articles concernant LINQ et les jointures multiples. Je n'ai cependant pas trouvé de solution au joint que je voudrais faire.

L'équivalent SQL serait quelque chose comme ceci:

SELECT * FROM table1 a
LEFT JOIN table2 b ON a.col1 = b.key1 AND
a.col2 = b.key2 AND
b.from_date <= now() AND
b.deleted = 0;

Voici l'une des nombreuses requêtes linq que j'ai tentées

var query = (from x in context.table1
             join y in context.table2 on new {x.col1, x.col2} equals {b.key1, b.key2} 
             into result
             from result......

Comment puis-je ajouter les conditions supplémentaires de la date et du drapeau supprimé? Si j'utilise des conditions .Where, cela est traité comme une jointure interne et non comme une jointure gauche.

33
Kman

Une autre façon pourrait être comme

var query = (from x in context.table1 
             join y in context.table2 on 
             new  {
                  Key1 = x.col1, 
                  Key2 = x.col2,
                  Key3 = true,
                  Key4 = true
                 }
             equals
             new {
                  Key1 = y.key1, 
                  Key2 =  y.key2,
                  Key3 = y.from_date< DateTime.Now,
                  Key4 = !y.deleted
                 }  
             into result
from r in result.DefaultIfEmpty()
select new  {x.Something, r.Something}
54

LINQ prend en charge la syntaxe de jointure et l'ancienne syntaxe ANSI-82 WHERE. En utilisant ce dernier, vous pouvez faire ce que vous recherchez sur une jointure interne avec

var nowTime = DateTime.Now;
var query = from a in context.table1
            from b in context.table2
            where a.col1 == b.key1
                 && a.col2 == b.key2 
                 && b.from_date < nowTime
                 && b.deleted == false
            select ???;

Pour une jointure externe, je préfère une syntaxe utilisant un hybride d'où et sélectionnez plusieurs. (Sachez que l'ordre dans la requête LINQ n'a pas besoin d'imiter ce que vous feriez dans SQL et l'ordre est plus flexible.)

var nowTime = DateTime.Now;
var query = from b in context.table2
            from a1 in a.Where(a2 => 
                b.key1 = a.col && 
                b.key2 = a.col2 &&
                b.from_date < nowTime &&
                b.deleted == false).DefaultIfEmpty()
            select ???;
15
Jim Wooley

J'ai eu un problème avec le nommage des propriétés dans un objet anonyme:

var subscriptions = context.EmailSubscription.Join(context.EmailQueue,
                    es => new { es.Id, 9 },
                    eq => new { eq.EmailSubscriptionId, eq.EmailTemplateId },
                    (es, eq) => new { es.Id, eq.Id }
                ).ToList();

Le compilateur n'était pas content, donc la réponse ci-dessus m'aide à comprendre ce qui n'allait pas et voici ma solution de travail. Il m'a fallu un certain temps pour trouver une erreur stupide :):

var subscriptions = context.EmailSubscription.Join(context.EmailQueue,
                    es => new { EmailSubscriptionId = es.Id, EmailTemplateId  = 9 },
                    eq => new { eq.EmailSubscriptionId, eq.EmailTemplateId },
                    (es, eq) => new { es.Id, eq.Id }
                ).ToList();
2
tonco

Ne pourriez-vous pas simplement filtrer le 1er jeu de résultats avec une deuxième requête?

var query = (from x in context.table1 
             join y in context.table2 on new {x.col1, x.col2} equals {b.key1, b.key2}  
             into result
query = from x in query
        where ...

Cela fonctionnerait-il?

1
james lewis

En plus de la réponse de @Muhammad Adeel Zahid, vous pouvez également utiliser plusieurs conditions telles que:

new
{
Key1 = ppl.PeopleId,
Key2 = true,
Key3 = true
}
equals
new
{
Key1 = y.PeopleId,
Key2 = !y.IsDeleted,
Key3 = (y.RelationshipType == 2 || y.RelationshipType == 4)
}
0
Leandro