2010-09-28 12 views
7

Teniendo en cuenta esta consulta:Problema con LINQ a Entidades consulta mediante la suma de la propiedad objeto secundario

from s in services 
select new 
{ 
    s.Id, 
    s.DateTime, 
    Class = s.Class.Name, 
    s.Location, 
    s.Price, 
    HeadCount = s.Reservations.Sum(r => r.PartySize), // problem here. r.PartySize is int 
    s.MaxSeats 
} 

Si el servicio no tiene ninguna reserva, esta excepción se produce:

System.InvalidOperationException : El lanzamiento al tipo de valor 'Int32' falló porque el valor materializado es nulo. O el parámetro genérico del tipo de resultado o la consulta debe usar un tipo anulable.

Lo entiendo, pero ¿cómo debo tratarlo? Mi intención es que si no hay reservas, a continuación, la plantilla se le asigna 0.

Respuesta

7

Debe comprobar que:

HeadCount = s.Reservations != null ? s.Reservations.Sum(r => r.PartySize) : 0, 
+0

he publicado esta pregunta antes de tratar de que sólo porque supuse que LINQ a ENTIDADES no sería capaz de convertir a SQL o algo como eso. Todavía me estoy acostumbrando a L2E, que parece mucho más quisquilloso que LINQ to SQL sobre lo que se podría hacer dentro de la declaración LINQ. De todos modos, esto funciona y uno nunca debería suponer. Gracias. –

+0

@Ronnie me alegro de que funcionó. Definitivamente son diferentes e imagino que L2E solo se volverá más flexible en el futuro. –

+0

Esto funcionará, pero hay una solución más fácil. –

1

Un operador ternario sencilla debe solucionar el problema muy bien ...

algo así como esto:

HeadCount = (s.Reservations != null && s.Reservations.Any()) ? s.Reservations.Sum(r => r.PartySize) : 0; 

este manejará para ambas situaciones nulos y vacíos

+0

No creo que el código siquiera se compile (falta '()'). Ciertamente no producirá SQL eficiente (nunca use '.Count() == 0' cuando quiera decir' Any() '), pero incluso eso es ineficiente y difícil de leer en comparación con. L2E incorporado nulo coalesce). –

+0

Tiene razón, no compilará porque Count no tiene el '()'. Lo escribió sobre la marcha -_-. Cualquiera también sería más eficiente. ¡Gracias por la corrección! –

11

Hay una solución aún más simple:

from s in services 
select new 
{ 
    s.Id, 
    s.DateTime, 
    Class = s.Class.Name, 
    s.Location, 
    s.Price, 
    HeadCount = (int?)s.Reservations.Sum(r => r.PartySize), 
    s.MaxSeats 
} 

Tenga en cuenta el elenco. Esto también puede producir SQL más simple que la sugerencia de @ Ahmad.

Esencialmente, usted está ayudando a cabo la inferencia de tipo.

+0

Según el OP 'Reservas' podría ser 'nulo', por lo que no es posible intentar 'Suma (...) 'en un nulo. Casting a 'int?' No omitiría la excepción nula que ocurriría en el tiempo de ejecución. Tal vez estabas pensando en emitir un valor nulo directamente, como '(int?) R.PartySize'? –

+2

@Ahmad, eso no es correcto para L2E, aunque es correcto para L2O. Ellos tienen diferentes reglas. No, no estoy pensando en arrojar el valor. Prueba el código que sugiero; funciona –

+1

+1 Pasé por alto la traducción que tiene lugar para este proveedor de LINQ. –

2

Esto debería resolver su problema: Trate de costado a la int a int?

from s in services 
select new 
{ 
    s.Id, 
    s.DateTime, 
    Class = s.Class.Name, 
    s.Location, 
    s.Price, 
    HeadCount = s.Reservations.Sum(r => (int?) r.PartySize), 
    s.MaxSeats 
}; 
HeadCount = HeadCount ?? 0; 
Cuestiones relacionadas