2
votes

Jointure de noyau EF avec plusieurs conditions OR

Je veux convertir cette requête SQL en linq:

select * from  A a
join B b on (a.level1= b.PerimeterID and  b.PerimeterLevelID = 1)
where (a.level2= b.PerimeterID and  b.PerimeterLevelID = 2)
       OR (a.level3= b.PerimeterID and  b.PerimeterLevelID = 3))

Ce que j'ai essayé:

from a in A
join b in B on new {PerimeterID = a.level1, PerimeterLevelID = 1 } equals new { b.PerimeterID, b.PerimeterLevelID }
where (a.level2 == b.PerimeterID && b.PerimeterLevelID == 2) ||
      (a.level3 == b.PerimeterID && b.PerimeterLevelID == 3)

cela génère cette requête SQL:

select * from  A a
join B b on (    (a.level1= b.PerimeterID and  b.PerimeterLevelID = 1)
              OR (a.level2= b.PerimeterID and  b.PerimeterLevelID = 2)
              OR (a.level3= b.PerimeterID and  b.PerimeterLevelID = 3)
            )

J'ai également essayé Linqer mais cela ne peut pas convertir OR en linq

SQL ne peut pas être converti en LINQ: OU

ce que je dois faire pour convertir cette requête SQL


0 commentaires

3 Réponses :


0
votes

vous pouvez essayer avec DefaultIfEmpty () . Les jointures se comporteront comme une jointure gauche avec cette commande

from a in A
from b in B.DefaultIfempty()
where (   (a.level1== b.PerimeterID &&  b.PerimeterLevelID == 1)
       || (a.level2== b.PerimeterID &&  b.PerimeterLevelID == 2)
       || (a.level3== b.PerimeterID &&  b.PerimeterLevelID == 3))


2 commentaires

Que fait le DefaultIfEmpty pour l'affiche originale? Sa plainte n'était pas qu'il n'obtenait pas d'enregistrements, mais que le SQL généré n'était pas ce qu'il voulait.


@OmarAMEZOUG J'ai corrigé le code. désolé Il semble que j'ai besoin de dormir :)



4
votes

Une jointure interne équivaut à une jointure croisée filtrée. Alors que diriez-vous de

from a in A
from b in B 
where (a.level1 == b.PerimeterID && b.PerimeterLevelID == 1) ||
      (a.level2 == b.PerimeterID && b.PerimeterLevelID == 2) ||
      (a.level3 == b.PerimeterID && b.PerimeterLevelID == 3)
select new {a,b};

?


2 commentaires

J'ai essayé cette solution mais elle génère un CROSS JOIN, je souhaite éviter car j'ai une table énorme, un problème de performance


un CROSS JOIN avec une clause WHERE est identique à un INNER JOIN à la fois pour la sémantique et (au moins dans SQL Server) pour les performances.



0
votes

Je pense que cette requête aidera

var query = from a in context.A
            join b1 in context.B
                on new { Perimeter = a.level1, LevelID = 1 }
                equals new { Perimeter = b1.PerimeterID, LevelID = b1.PerimeterLevelID }
            join b2 in context.B
                on new { Perimeter = a.level2, LevelID = 2 }
                equals new { Perimeter = b2.PerimeterID, LevelID = b2.PerimeterLevelID }
            join b3 in context.B
                on new { Perimeter = a.level3, LevelID = 3 }
                equals new { Perimeter = b3.PerimeterID, LevelID = b3.PerimeterLevelID }
            select new
            {
                a,
                b1,
                b2,
                b3
            };


0 commentaires