Pregunta

he hecho una pregunta anterior sobre qué une a izquierda en LINQ no pueden utilizar relaciones definidas ; hasta la fecha no tengo una respuesta satisfactoria.

Ahora, en una vía paralela, he aceptado que tengo que utilizar la palabra clave join como si no hubiera ninguna relación definida entre mis objetos, y yo estoy tratando de encontrar la manera de expresar mi consulta en LINQ. El problema es que se trata de un conglomerado de izquierda se une entre varias tablas, con múltiples campos implicados en la unión. No hay manera de simplificar esto, así que aquí está el SQL en todo su esplendor desenmascarado:

select *
from TreatmentPlan tp
join TreatmentPlanDetail tpd on tpd.TreatmentPlanID = tp.ID
join TreatmentAuthorization auth on auth.TreatmentPlanDetailID = tpd.ID
left join PatientServicePrescription rx on tpd.ServiceTypeID = rx.ServiceTypeID
left join PayerServiceTypeRules pstr on auth.PayerID = pstr.PayerID and tpd.ServiceTypeID = pstr.ServiceTypeID and pstr.RequiresPrescription = 1
where tp.PatientID = @PatientID

(FYI, si ayuda a entender lo que estoy tratando de hacer: Estoy tratando de identificar si hay registros TreatmentPlanDetail de este Patient donde el Payer autorización requiere una receta para este ServiceType, pero o bien no hay ServicePerscription registro, o ha expirado.)

Ahora, aquí está lo que mi código C # es así:

var q = from tp in TreatmentPlans
        from tpd in tp.Details
        from auth in tpd.Authorizations
        join rx in ServicePrescriptions.DefaultIfEmpty() on tpd.ServiceTypeID equals rx.ServiceTypeID
        // from pstr in auth.Payer.ServiceTypeRules.DefaultIfEmpty() -- very frustrating that this doesn't work!!
        join pstr in LinqUtils.GetTable<PayerServiceTypeRules>().DefaultIfEmpty()
        on new { auth.PayerID, tpd.ServiceTypeID, RxReq = (bool)true } equals new { pstr.PayerID, pstr.ServiceTypeID, pstr.RequiresPrescription }
        select new { Payer = auth.Payer, Prescription = rx, TreatmentPlanDetail = tpd, Rules = pstr };

Vaya, no se compila! Por alguna razón (me gustaría una explicación) no puedo usar ese booleano literal dentro de la combinación de igualdad! Bien, lo dejaré fuera, y filtrar las cosas "RequiresPrescription" más adelante ...

...
join pstr in LinqUtils.GetTable<PayerServiceTypeRules>().DefaultIfEmpty()
on new { auth.PayerID, tpd.ServiceTypeID } equals new { pstr.PayerID, pstr.ServiceTypeID }
...

... y ahora se compila - pero cuando corro, me sale un "Referencia a objeto no establecida" excepción en esta línea. DUH! Por supuesto que hay un nulo en allí! ¿Cómo, si se supone que para llevar a cabo una comparación con una combinación izquierda, si no se le permite hacer referencia al objeto en el lado derecho, que podría potencialmente ser nulo?

Así que, ¿cómo se supone que hacer una combinación izquierda utilizando múltiples campos?

¿Fue útil?

Solución

Creo que es necesario utilizar la palabra clave into y resolver DefaultIfEmpty de los niños perdidos () después la unión, no antes:

...
join pstr in LinqUtils.GetTable<PayerServiceTypeRules>()
on new { auth.PayerID, tpd.ServiceTypeID, bool RequiresPrescription = true } 
equals new { pstr.PayerID, pstr.ServiceTypeID, pstr.RequiresPrescription } 
into pstrs
from PSTR in pstrs.DefaultIfEmpty()
select new { 
    Payer = auth.Payer, 
    Prescription = rx, 
    TreatmentPlanDetail = tpd, 
    Rules = PSTR 
};

LinqUtils.GetTable<PayerServiceTypeRules>().DefaultIfEmpty() es, probablemente, apareciendo un nulo porque el DataTable devuelta contiene ninguna fila , por tanto, la causa de su excepción. Tenga en cuenta toda la declaración después de in se ejecutará antes de seleccionar en ella, que no es el comportamiento deseado. Desea que las filas coincidentes o nula si no existen filas coincidentes.


Para el problema booleano, es un problema de nomenclatura (nada se compara con "RxReq" en el lado derecho y nada se compara con "RequiresPrescription" en el lado izquierdo). Intenta nombrar el "RequiresPrescription" true como lo he hecho anteriormente (o el nombre de la parte derecha pstr.RequiresPrescription "RxReq").

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top