web-dev-qa-db-fra.com

Comment forcer LINQ Sum () à renvoyer 0 alors que la collection source est vide

Fondamentalement, lorsque je fais la requête suivante, si aucun prospect ne correspond, la requête suivante lève une exception. Dans ce cas, je préférerais que la somme soit égale à 0 plutôt qu’une exception ne soit levée. Serait-ce possible dans la requête elle-même - je veux dire plutôt que de stocker la requête et de vérifier query.Any()?

double earnings = db.Leads.Where(l => l.Date.Day == date.Day
                && l.Date.Month == date.Month
                && l.Date.Year == date.Year
                && l.Property.Type == ProtectedPropertyType.Password
                && l.Property.PropertyId == PropertyId).Sum(l => l.Amount);
166
John Mayer

Essayez de changer votre requête à ceci:

db.Leads.Where(l => l.Date.Day == date.Day
            && l.Date.Month == date.Month
            && l.Date.Year == date.Year
            && l.Property.Type == ProtectedPropertyType.Password
            && l.Property.PropertyId == PropertyId)
         .Select(l => l.Amount)
         .DefaultIfEmpty(0)
         .Sum();

Ainsi, votre requête ne sélectionnera que le champ Amount. Si la collection est vide, il retournera un élément avec la valeur 0 et la somme sera appliquée.

353
Simon Belanger

Je préfère utiliser un autre hack:

double earnings = db.Leads.Where(l => l.Date.Day == date.Day
                                      && l.Date.Month == date.Month
                                      && l.Date.Year == date.Year
                                      && l.Property.Type == ProtectedPropertyType.Password
                                      && l.Property.PropertyId == PropertyId)
                          .Sum(l => (double?) l.Amount) ?? 0;
165
tukaef

Essayez plutôt ceci, c'est plus court:

db.Leads.Where(..).Aggregate(0, (i, lead) => i + lead.Amount);
5
Kovács Róbert

C'est gagner pour moi:

int Total = 0;
Total = (int)Db.Logins.Where(L => L.id == item.MyId).Sum(L => (int?)L.NumberOfLogins ?? 0);

Dans ma table LOGIN, dans le champ NUMBEROFLOGINS, certaines valeurs sont NULL et d'autres ont un numéro INT. Je résume ici le nombre total de NUMBEROFLOGINS de tous les utilisateurs d’une société (chaque identifiant).

3
Pedro Ramos
db.Leads.Where(l => l.Date.Day == date.Day
        && l.Date.Month == date.Month
        && l.Date.Year == date.Year
        && l.Property.Type == ProtectedPropertyType.Password
        && l.Property.PropertyId == PropertyId)
     .Select(l => l.Amount)
     .ToList()
     .Sum();
0
Mona

Mise à jour: Bien que la solution soit efficace, , cette réponse est incorrecte . Le bon est celui donné par Simon Bélanger. Néanmoins, au lieu de supprimer, je le laisse ici comme information supplémentaire (voir commentaires).

Le détail intéressant ici est que LINQ To implémentation SQL de Sum (celui que vous utilisez) diffère de LINQ To Objects 1. La réponse de Simon Bélanger est correcte et elle me plaît, mais (pour ne pas chercher très loin), une autre option pour que cela fonctionne est de changer le type de compilation du source. et utilisation de LINQ To Objects. Les différents Sum seront exécutés (sans aucune opération supplémentaire requise):

db.Leads.Where(...)
        .AsEnumerable() // switch to LINQ to Objects
        .Sum(l => l.Amount);

De MSDN :

La méthode AsEnumerable (IEnumerable) n'a d'autre effet que de modifier le type de compilation de la source au moment de la compilation d'un type qui implémente IEnumerable en IEnumerable lui-même.

0
jwaliszko