2011-12-29 10 views
12

Se faccio:Perché la somma di un set vuoto è nulla?

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

Se non vengono restituiti record in questa query getta:

System.InvalidOperationException: il valore null non può essere assegnato a un membro con il tipo System.Int32 che è un tipo di valore non annullabile.

L'unico modo per farlo tornare 0 è facendo:

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

Nel database c.Plays è un int non annullabile.

In teoria dell'insieme la somma di un set vuoto deve essere uguale a 0 (ref). Come mai in Linq-to-SQL hanno deciso di farlo restituire null?

+4

Questo è più database e meno teoria degli insiemi. Qual è il 'SUM' di una colonna nullable in SQL Server? – Marc

+0

@Marc nella domanda I link a nessuna delle colonne in questione sono annullabili –

+1

Il dbml L2S sa che per questo set di dati? Assumerei che il campo sarebbe un 'int' e non un' int? 'Se è così. – Marc

risposta

9

According to a source at Microsoft, Sum() su un insieme vuoto è null a causa del modo in cui funziona in SQL:

quando il tavolo è vuoto sto ottenendo questa eccezione: InvalidOperationException

In SQL, l'operatore di aggregazione Sum() restituisce null per un set vuoto. Quindi questo è come progettato.

+16

"... come errato. " – starblue

+1

Ma se si utilizza Sum su un oggetto IEnumerable vuoto, restituisce correttamente 0. Quindi, Microsoft ha scelto di rendere Sum() su IQueryable per essere coerente con SQL ma incoerente con Sum() su IEnumerable. Scelta ambigua ... – JustAMartin

0

È possibile utilizzare il metodo più generale Aggregate con un seme zero:

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

Questo non richiede utilizzando i tipi nullable.

+0

Non so LINQ su SQL, ma LINQ su Entità non supporta 'Aggregazione'. –

2

Un'altra alternativa è aggiungere uno 0 all'insieme per assicurarsi che ci sia sempre almeno un valore.

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