2014-06-05 3 views
2

J'ai actuellement certaines procédures stockées dans T-SQL que je voudrais traduire en entités LINQ-To pour une meilleure maintenabilité. Cependant, peu importe comment je semble construire la requête LINQ, quand j'inspecte le code généré, c'est une horrible monstruosité terriblement performante. J'ai étudié diverses combinaisons de clauses "let", jointures, déplaçant la clause "where" à la fois à l'intérieur et à l'extérieur de la sélection de type anonyme, ou même en utilisant l'extension ".Where <>()" méthode fragmentaire dans le d'autres indications, et rien ne semble générer de code aussi proche de ce à quoi je m'attendrais ou dont j'aurais besoin.LINQ to Entities - Jointures multiples sur la même table

Les difficultés semblent triple:

  • Le joint que je dois faire sont sur des combinaisons de booléens, alors que LINQ-To-entités semble ne se joigne à la fonctionnalité pour équijointures. Comment puis-je traduire ces jointures?
  • Je dois joindre sur la même table plusieurs fois différentes avec des clauses join/where différentes, de sorte que je puisse sélectionner une valeur différente pour chaque enregistrement. Comment puis-je accomplir cela dans LINQ-To-Entities? Comment éviter que mes jointures sur les collections d'entités ne deviennent des mess imbriqués?

La requête T-SQL que je tente de traduire est ce (où les chiffres sont les types hardcoded spécifiques hardcoded):

SELECT Transport.*, 
    [Address].Street1, 
    Carrier1Insurance.InsuranceNumber, 
    Carrier2Insurance.InsuranceNumber, 
    Carrier3Insurance.InsuranceNumber 
FROM Transport 
INNER JOIN Appoint ON Transport.AppointKEY = Appoint.AppointKEY 
INNER JOIN Patient ON Appoint.PatientKEY = Patient.PatientKEY 
LEFT OUTER JOIN [Address] ON [Address].AddressFKEY = Patient.PatientKEY AND [Address].AddressTypeByTableKEY = 1 
LEFT OUTER JOIN PatientInsurance Carrier1Insurance ON Carrier1Insurance.PatientKEY = Patient.PatientKEY AND Carrier1Insurance.CarrierKEY = 7 
LEFT OUTER JOIN PatientInsurance Carrier2Insurance ON Carrier2Insurance.PatientKEY = Patient.PatientKEY AND Carrier2Insurance.CarrierKEY = 8 
LEFT OUTER JOIN PatientInsurance Carrier3Insurance ON Carrier3Insurance.PatientKEY = Patient.PatientKEY AND (Carrier3Insurance.CarrierKEY <> 7 AND Carrier3Insurance.CarrierKEY = 8) 
WHERE (Transport.TransportDate >= '07-01-2013' AND Transport.TransportDate <= '07-31-2013') 
AND EXISTS (SELECT TOP 1 * 
       FROM Remit 
       WHERE Remit.CarrierKEY = 8 
        AND Remit.AppointKEY = Transport.AppointKEY 
        AND Remit.PaidAmt > 0) 

Et la dernière dans de nombreux, de nombreuses tentatives de LINQ est la suivante:

var medicareTransportList = from transportItem in ClientEDM.Transports 
         join patientAddress in ClientEDM.Addresses on transportItem.Appoint.PatientKEY equals patientAddress.AddressFKEY 
         join carrier1Insurance in ClientEDM.PatientInsurances on transportItem.Appoint.PatientKEY equals carrier1Insurance.PatientKEY 
         join carrier2Insurance in ClientEDM.PatientInsurances on transportItem.Appoint.PatientKEY equals carrier2Insurance.PatientKEY 
         join otherInsurance in ClientEDM.PatientInsurances on transportItem.Appoint.PatientKEY equals otherInsurance.PatientKEY 
         where (transportItem.TransportDate > fromDate ** transportItem.TransportDate <= toDate) && transportItem.Appoint.Remits.Any(remit => remit.CarrierKEY == 0 && remit.PaidAmt > 0.00M) && 
           (carrier1Insurance.CarrierKEY == 7) && 
           (carrier2Insurance.CarrierKEY == 8) && 
           (otherInsurance.CarrierKEY != 7 && 
           otherInsurance.CarrierKEY != 8) && 
           (patientAddress.AddressTypeByTableKEY == 1) 
         select new 
         { 
          transport = transportItem, 
          patient = patientAddress, 
          medicare = medicareInsurance, 
          medicaid = medicaidInsurance, 
          other = otherInsurance 
         }; 
+1

Quel est le problème avec votre dernière itération? Voir aussi http://stackoverflow.com/questions/3725032/greater-than-condition-in-linq-join pour les jointures non égales. – Vulcronos

+0

Est-ce que cela a du sens de simplement charger les entités qui dépendent des transports au besoin, ou avez-vous vraiment besoin de toutes ces données à l'avance? –

+0

@Vulcronos le problème avec l'itération la plus récente est qu'il génère une instruction SQL de plusieurs centaines de lignes qui prend> 30 secondes pour produire un résultat, alors que la requête in-SQL est évidemment juste quelques dizaines et accomplit la tâche en seulement peu. De plus, le problème n'est pas tant que c'est une jointure non-égale, mais sur plusieurs critères. L'instruction "from" supplémentaire génère une jointure croisée pour plusieurs milliers de lignes. – Mejwell

Répondre

0

l'opérateur LINQ .Join() est équivalent à l'opérateur INNER JOIN SQL.

Pour tout autre cas, utilisez l'opérateur .GroupJoin().

Mais avez-vous vraiment besoin d'utiliser join? Dans de nombreux cas, en utilisant LINQ, SQL JOIN (interne ou externe) peut être exprimé en utilisant les propriétés de navigation entre les entités.

Veuillez expliquer votre modèle de données conceptuel pour une réponse précise.