web-dev-qa-db-ja.com

ソースコレクションが空のときにLINQ Sum()が強制的に0を返す方法

基本的に次のクエリを実行するときに、一致するリードがない場合、次のクエリは例外をスローします。その場合、例外がスローされるのではなく、合計が0に等しくなるようにします。これはクエリ自体で可能ですか?クエリを保存して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);
159
John Mayer

クエリを次のように変更してみてください。

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();

この方法では、クエリはAmountフィールドのみを選択します。コレクションが空の場合、0の値を持つ1つの要素が返され、合計が適用されます。

343
Simon Belanger

私は別のハックを使用することを好みます:

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;
159
tukaef

代わりにこれを試してください、それは短いです:

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

それは私にとって勝利です。

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

私のLOGINテーブルでは、フィールドNUMBEROFLOGINSの一部の値はNULLであり、他の値はINT番号を持っています。ここで、ある法人の各ユーザーの合計NUMBEROFLOGINSを合計します(各ID)。

2
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

更新:実用的なソリューションですが、この答えは間違っています。明らかに正しいものはサイモン・ベランジャーによって与えられたものです。それでも、削除する代わりに、ここに補足情報として残します(コメントを参照)。

ここで興味深い詳細は、SumのLINQ To SQL実装です(これは明らかに使用しています)とは異なりますLINQ To Objectsの1つです。Simon Belangerの答えは正しいので気に入っていますが、これを機能させる別のオプションは、ソースのコンパイルタイプとLINQ Toオブジェクト。異なるSumが実行されます(追加の操作は必要ありません):

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

MSDN から:

AsEnumerable(IEnumerable)メソッドは、ソースのコンパイル時の型を、IEnumerableを実装する型からIEnumerable自体に変更する以外の効果はありません。

0
jwaliszko