2016-01-22 26 views
5

Tentativo di ottenere i valori restituiti da un database in base alla somma di un campo.MVC da linq a sql sum

Ma ottenere questo messaggio:

Il cast al tipo di valore 'System.Decimal' riuscita perché il materializzato valore è nullo. Il parametro generico del tipo di risultato o la query devono utilizzare un tipo nullable.

È valido per il database per non contenere alcun record per quell'utente per quel giorno, quindi sono andato giù per la rotta nullable. Nei bei vecchi tempi avrei costruito una stored procedure con `ISNULL` in essa !!!

Questa è l'espressione di base che ho:

decimal? foodCount = dbContext.fad_userFoods.Where(uf => uf.dateAdded == thisDate && uf.userID == thisGuid).Sum(uf=>(decimal?)uf.quantityAmount ?? 0m);

googling si avvicinò con le definizioni nullable e l'uso del ?? con la "m" come decimale. Ma ancora l'errore persiste!

Il tuo aiuto collettivo sarà inestimabile come sempre. Grazie in anticipo.

risposta

6

Utilizzare il metodo DefaultIfEmpty. Questo riempirà uno 0 se non si trova alcun valore.

decimal foodCount = dbContext.fad_userFoods 
    .Where(uf => uf.dateAdded == thisDate && uf.userID == thisGuid) 
    .Select(uf => uf.quantityAmount) 
    .DefaultIfEmpty() 
    .Sum(); 
+0

Bingo! Grazie Maarten, questo ha fatto il trucco. Ancora tanto da imparare su linq su sql! – stumcc

3

Utilizzare Convert.ToDecimal(), questo gestirà il problema nullo.

decimal foodCount = dbContext.fad_userFoods.Where(uf => uf.dateAdded == thisDate 
                && uf.userID == thisGuid) 
              .Sum(uf=> Convert.ToDecimal(uf.quantityAmount ?? 0m)); 

LINQ alle entità non riconosce il metodo '(System.Decimal) System.Decimal ToDecimal' metodo, e questo metodo non può essere tradotto in un'espressione negozio.

Edit:

decimal foodCount = dbContext.fad_userFoods.Where(uf => uf.dateAdded == thisDate 
                && uf.userID == thisGuid) 
              .Sum(uf=> { decimal result; 
                 decimal.TryParse(uf.quantityAmount,out result); 
                 return result;}); 
+0

Avevo provato che in precedenza, ma appena provato di nuovo e questo messaggio di errore: LINQ alle entità non riconosce il metodo metodo 'System.Decimal ToDecimal (System.Decimal)' e questo metodo non può essere tradotto in un'espressione di archivio. – stumcc

+0

@stumcc: Ho aggiornato la mia risposta per favore dare un'occhiata. – Prabhat

3

Dal momento che è un valore nullo valori sum e non average in realtà non mente? Perché non rimuovere semplicemente i valori null?

decimal? foodCount = dbContext.fad_userFoods 
     .Where(uf => 
     uf.dateAdded == thisDate && 
     uf.userID == thisGuid && 
     uf.quantityAmount != null) 
     .Sum(uf=> uf.quantityAmount); 
+0

Fondamentalmente sto cercando alcuni alimenti che qualcuno ha mangiato in un giorno. Quindi può essere che quella persona non abbia mangiato quegli alimenti, quindi la somma dell'importo sarà 0 poiché non esistono sul tavolo. – stumcc

+1

Sì, ma in questo caso null deve essere convertito in 0, che equivarrebbe a non contarlo affatto. Quindi escluderlo nella clausola where potrebbe sottrarsi completamente al problema, ma dare comunque la stessa somma. Inoltre, evita qualsiasi conversione di tipi nel database. – smoksnes

2

La confusione nasce dal fatto il Sum in LINQ alle entità viene elaborato un po 'diverso in LINQ agli oggetti. Anche se dalla dichiarazione sembra che chiamandolo su un enunciato decimal restituirà 0, quando il set di destinazione è vuoto in realtà la funzione SQL SUM restituisce NULL, anche se la colonna di destinazione non è annullabile.

Una volta che lo sai, ci sono due modi per risolverlo.

Let dire che abbiamo un tavolo con decimal colonna e l'espressione originale è

table.Sum(item => item.Column) 

primo modo è quello di convertire utilizzando il modello contenuto nella Maarten answer:

table.Select(item => item.Column).DefaultIfEmpty().Sum() 

Il secondo modo è convertire esplicitamente il tipo non annullabile in null nella funzione e quindi applicare operatore con coalizione nulla al risultato :

table.Sum(item => (decimal?)item.Column) ?? 0 

Entrambi i modi lavorare e produrre uno e lo stesso risultato, in modo da utilizzare quello che si adatta meglio alle preferenze personali.

Per completezza, applicando il secondo approccio nel tuo caso sarebbe quello di spostare sostanzialmente la ?? 0 al di fuori del Sum chiamata:

decimal foodCount = dbContext.fad_userFoods 
    .Where(uf => uf.dateAdded == thisDate && uf.userID == thisGuid) 
    .Sum(uf => (decimal?)uf.quantityAmount) ?? 0;