I currently have some stored procedures in T-SQL that I would like to translate to LINQ-To-Entities for greater maintainability. However, no matter how I seem to construct the LINQ query, when I inspect the generated code, it's an abhorrent terribly-performing monstrosity. I've investigated into various combinations of "let" clauses, joins, shifting around the "where" clause to both inside and out of the anonymous type selection, or even using the extension ".Where<>()" method piecemeal in the other indiciations themselves, and nothing seems to generate code anywhere as close to what I would expect or need.
The difficulties seem threefold:
- The joins that I need to do are on combinations of booleans, whereas LINQ-To-Entities seems to only have join functionality for equijoins. How can I translate these joins?
- I need to join on the same table multiple different times with different join/where clauses, so that I can select a different value for each record. How do I accomplish this in LINQ-To-Entities?
- How do I prevent my joins on entity collections become nested messes?
The T-SQL query I'm attempting to translate is this (where the hardcoded numbers are specific hardcoded types):
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)
And the latest in many, many attempts at LINQ is this:
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
};