2009-02-23 15 views
17

私はこのコードを持っていないときに0を返すの例外が発生する(OK、私はしませんが、似たような:P)ここで合計は()の代わりに行が

var dogs = Dogs.Select(ø => new Row 
    { 
      Name = ø.Name, 
      WeightOfNiceCats = ø.Owner 
       .Cats 
       .Where(æ => !æ.Annoying) 
       .Sum(æ => æ.Weight), 
    }); 

は、私はすべての犬を通過し、総括犬と同じ所有者を持つすべての非厄介な猫の体重(非ヌル値の10進数に)。もちろん、ほとんどすべての猫は迷惑しているので、私はこのエラーを取得する:使用されるフィールドまたは外部キーの

The null value cannot be assigned to a member with type System.Decimal which is a non-nullable value type.

なしがnullになることはできません。したがって、エラーは、Where節が猫を返さない場合に起こります。しかし、どうすればこの問題を解決できますか?私はそれが起こったときに0を返すようにしたい。 Where句の後DefaultIfEmpty()てみましたが、その後、私はこのエラーを取得する:私は理解しやすいと思い

Object reference not set to an instance of an object.

。私はSum??を追加しようとしましたが、それは文句を言わないこのエラーのためコンパイル:

Operator '??' cannot be applied to operands of type 'decimal' and 'decimal'

も当然の理にかなって。じゃあどうすればいい?合計するものがないときにSumのものが0を返しただけでいいですか?またはSumOrZeroなんらかのステートメント。 Linq2SQLと連携してSumOrZeroメソッドを作成するのは難しいですか?

+1

大きな質問です。この現象はMSDNに記載されていないように思われます。 – Mykroft

答えて

20

これは私が今のところしてしまったものです:

.Sum(æ => (decimal?) æ.Weight) ?? 0.0M, 

これは魔法のように動作します。

null何らかの理由で決して返さないことを除いて、通常のSumとまったく同じように動作するSumOrZeroを使用することをお勧めします。他の人たちと同じように、これはIEnumerableの方がかなり簡単ですが、IQuearyableのために作成するのはちょっと厄介なので、Linq2SQLなどではうまくいくでしょう。誰かが退屈していて、SumOrZeroIQueryablesと書くと、すべての数値型でLinq2SQLと動作しますが、私に知らせてください:D

+0

小さな誤植 - 'decimal'があるはずです* –

+1

@Danielこれは間違いありません!誰かが気付いて通知するのに5年しかかかりませんでした。 – Svish

3

既に与えられているトリック(.Sum(æ => (decimal?) æ.Weight) ?? 0.0M)は、このシナリオがデータベースでクエリとして実行されたときに考えられる最高のものです。少し面倒ですが、悪いことがあります...

LINQ-to-Objectsとは異なり、独自の拡張メソッドを追加することはできません。これは、基になるプロバイダによってマップされる必要があるためです。

+0

。それは私が恐れていたことだった、hehe。 – Svish

5

LINQ to Objectsでは簡単です。 LINQ to SQLでは難しくなります。 Queryable.Sumと呼ばれる独自の拡張メソッドを書くことができます。正規表現から式を構築し、null可能な型にキャストします。私はあなたがする必要があると思う?? 0mの呼び出しコードです。言い換えれば、あなたが行うことができます:

public static decimal? SumOrNull<TSource, decimal>(this IQueryable<TSource>, 
    Func<TSource,decimal> projection) 

あなたは基本的に照会可能でサポートされるすべての値の型のためにそれを書くことができる:.SumOrNullのシグネチャは次のようになり

.SumOrNull(æ => æ.Weight) ?? 0M, 

を。あなたはそれを一般的に書くことができ、反射を使用してクエリ可能な適切なメソッドを呼び出すが、それはあまりにも厄介です。

私は、正直言って、あなたが持っているものに最も適していると思います。

+0

それから私はちょうど私が持っているようにそれを残すと思う。 – Svish

0

DefaultIfEmptyを使用すると、単一の要素が0のIEnumberableが返され、意味的には同じ意味になります。

null可能な10進数を使用しているため、おそらく2つのパラメータを取るメソッドの2番目のバージョンを使用する必要があります。

+1

かなり反対;小数はNULL値ではありません。 LINQ-to-SQLグリッチに対する*回避策*は、計算のためにNULL値にすることです。 –

+0

それはさらに簡単です:) – leppie

+1

DefaultIfEmptyは、 "オブジェクト参照がオブジェクトのインスタンスに設定されていません。" – Svish

関連する問題