2011-12-29 25 views
12

Si hago:¿Por qué la suma de un conjunto vacío es nula?

int updateGamePlays = db.tblArcadeGames.Where(c => c.ParentGameID == GameID).Sum(c => c.Plays); 

Si no hay registros se devuelven en esta consulta se lanza:

System.InvalidOperationException: El valor nulo no puede ser asignado a un miembro de con el tipo System.Int32 cuales es un tipo de valor que no admite nulos.

La única manera de conseguir que vuelva 0 es haciendo:

int updateGamePlays = db.tblArcadeGames.Where(c => c.ParentGameID == GameID).Sum(c => (int?)c.Plays) ?? 0; 

En la base de datos c.Plays es un int no anulable.

En la teoría de conjuntos, la suma de un conjunto vacío debe ser igual a 0 (ref). ¿Cómo es que en Linq-to-SQL decidieron devolverlo al null?

+4

Esto es más base de datos y menos teoría de conjuntos. ¿Cuál es la 'SUMA 'de una columna que admite nulos en SQL Server? – Marc

+0

@Marc en la pregunta que enlazo a ninguna de las columnas en cuestión son nullable –

+1

¿Sabe L2S dbml que para este conjunto de datos? Supongo que ese campo sería un 'int' y no un' int? 'Si es así. – Marc

Respuesta

9

According to a source at Microsoft, Suma() en un conjunto vacío es null debido a la forma en que funciona en SQL:

cuando la tabla está vacía Estoy recibiendo esta excepción: InvalidOperationException

En El operador agregado SQL, Sum() devuelve null para un conjunto vacío. Así que esto es como está diseñado.

+16

"... como mal diseñado. " – starblue

+1

Pero si usa la suma en un IEnumerable vacío, entonces devuelve 0. Entonces, Microsoft eligió hacer que Sum() en IQueryable sea consistente con SQL pero inconsistente con Sum() en IEnumerable. Elección ambigua ... – JustAMartin

0

Se puede utilizar el método más general Aggregate con una semilla de cero:

int updateGamePlays = db.tblArcadeGames 
    .Where(c => c.ParentGameID == GameID) 
    .Aggregate(0, (a, c) => a + c.Plays); 

Esto no requiere el uso de tipos anulables.

+0

No sé sobre LINQ to SQL, pero LINQ to Entities no admite 'Aggregate'. –

2

Otra alternativa es agregar un 0 al conjunto para asegurarse de que siempre haya al menos un valor.

int updateGamePlays = db.tblArcadeGames.Where(c => c.ParentGameID == GameID) 
             .Select(c => c.Plays) 
             .Concat(new [] { 0 }) 
             .Sum(); 
Cuestiones relacionadas