2011-07-28 12 views
156

次のコードがあります。私はエラーが発生しています:実体化された値がnullであるため、値型 'Int32'へのキャストが失敗しました

"The cast to value type 'Int32' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type."

CreditHistoryテーブルにレコードがない場合。

var creditsSum = (from u in context.User 
        join ch in context.CreditHistory on u.ID equals ch.UserID           
        where u.ID == userID 
        select ch.Amount).Sum(); 

null値を受け入れるようにクエリを変更するにはどうすればよいですか?

答えて

272

にヌルを変換するためにnull合体演算子を使用して、NULL可能Amountフィールドを可能にします。場合によっては予期しない動作を引き起こす「漏れた抽象」であることがあります。

このようなケースの1つは、異なる場所で予期しないヌルが存在する場合があるnull処理です。 ...DefaultIfEmpty(0).Sum(0)は何の要素とSQLのSUM戻っ#Cに対しnullがないかもしれません。この(非常に簡単)場合、に助けることができる期待して0

より一般的なアプローチは、リスクがあるたびにCOALESCEに変換されます??を使用することですこの表現は確かにSum()intを返すにもかかわらず、nullを返すことができますC#コンパイラに指示するint?

var creditsSum = (from u in context.User 
       join ch in context.CreditHistory on u.ID equals ch.UserID           
       where u.ID == userID 
       select (int?)ch.Amount).Sum() ?? 0; 

この最初のキャスト:生成されたSQLは、予期しないヌルを返すこと。次に、通常の??演算子を使用してnullケースを処理します。

この回答に基づいて、LINQ to SQLとLINQ to Entitiesの詳細についてblog postと書いています。

+3

Anders、DefaultIfEmpty(0).Sum()のソリューションは、私のためにうまく動作します。私はまた、(int?)で2番目のソリューションを試してみましたか? 0 ...しかし、前と同じ例外がスローされます。 – zosim

+0

最後にこれをテストして調整したので、今度は2番目のバージョンも機能します。 –

+0

空のデータセットに適用すると、Sum()やその他の集計関数はnullを返します。それらの定義とは対照的に、実際には、基になる型のnull可能なバージョンを返します。 – Suncat2000

8

だけLINQツーSQLクエリをコードとして実行ではなく、SQLに翻訳されない0

var creditsSum = (from u in context.User 
       join ch in context.CreditHistory on u.ID equals ch.UserID           
       where u.ID == userID 
       select ch.Amount ?? 0).Sum(); 
+1

私はあなたのヒントを使用し、コンパイラは言う:演算子「? ? ' 'int'と 'int'型のオペランドには適用できません。何か忘れましたか? – zosim

+0

@zosim:これが最初に 'int?'にキャストを追加する理由です。 –

+0

intを追加しましたが、同じ例外があります。あなたがdev envを持っている時、私はあなたに感謝します。この構文で何が間違っているかを調べる。 – zosim

5
あなたは、あなたがLINQクエリは以下のようにいくつかの結果を与えていることを確認しなければならない項目がアクションを実行するために得ていない aggregate機能を使用している

:私はこのコードを使用することだし、それが正しく応答

var maxOrderLevel =sdv.Any()? sdv.Max(s => s.nOrderLevel):0 
+9

これはsdvを2回実行させるでしょう。あなたはIQueryablesのためにあなたが望むものではありません – Ody

1

を、のみ出力値はNULL可能です。

var packesCount = await botContext.Sales.Where(s => s.CustomerId == cust.CustomerId && s.Validated) 
           .SumAsync(s => (int?)s.PackesCount); 
          if(packesCount != null) 
          { 
           // your code 
          } 
          else 
          { 
           // your code 
          } 
1

これは既に回答済みです。しかし、それを2つのステートメントに分割したい場合は、以下のように考えることができます。

var credits = from u in context.User 
       join ch in context.CreditHistory 
        on u.ID equals ch.UserID           
       where u.ID == userID 
       select ch; 

var creditSum= credits.Sum(x => (int?)x.Amount) ?? 0; 
+1

私のために働く... –

2

ビューから選択しようとしたときにこのエラーメッセージが表示されました。

ビューは最近、(SubscriberId列の)いくつかの新しいヌル行を取得し、EDMX(EFデータベース)で更新されていないという問題がありました。

この列は、機能するにはNULL型でなければなりませんでした。

var dealer = Context.Dealers.Where(x => x.dealerCode == dealerCode)。FirstOrDefault();ビューのリフレッシュ後

public int SubscriberId { get; set; } 

public Nullable<int> SubscriberId { get; set; } 

削除とバックEDMXで働いていたビューを追加するビューをリフレッシュする前に

誰かを助けることを願っています。

0

は、実行時にこのコードでEntity Frameworkの6で、このエラーを得た:

var fileEventsSum = db.ImportInformations.Sum(x => x.FileEvents) 

はこれに変更し、それが働いた:

var fileEventsSum = db.ImportInformations.Any() ? db.ImportInformations.Sum(x => x.FileEvents) : 0; 
関連する問題