web-dev-qa-db-ja.com

マテリアライズされた値がnullであるため、値型 'Int32'へのキャストに失敗しました

私は次のコードを持っています。エラーが発生しています:

「マテリアライズされた値がnullであるため、値型 'Int32'へのキャストに失敗しました。結果の型のジェネリックパラメータまたはクエリのいずれかがnull許容型を使用する必要があります。」

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値を受け入れるようにクエリを変更するにはどうすればよいですか?

183
zosim

Linq-to-sqlクエリはコードとして実行されるのではなく、SQLに変換されます。時には、これは予期しない動作をもたらす「漏れやすい抽象化」です。

そのような場合の1つは、さまざまな場所に予期しないヌルが存在する可能性があるヌル処理です。 ...DefaultIfEmpty(0).Sum(0)は、この(非常に単純な)場合に役立ちます。要素がない場合、SQLのSUMnullを返しますが、c#は0を期待します。

より一般的なアプローチは、生成されたSQLが予期しないnullを返すリスクがある場合はいつでもCOALESCEに変換される??を使用することです。

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;

これは最初にint?にキャストして、C#コンパイラーに、Sum()nullを返しても、実際にこの式がintを返すことができることを伝えます。次に、通常の??演算子を使用して、nullのケースを処理します。

この回答に基づいて、 ブログ投稿 LINQ to SQLとLINQ to Entitiesの両方の詳細を書いた。

315
Anders Abel

Null許容のAmountフィールドを許可するには、null合体演算子を使用してnullを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();
8
recursive

アクションを実行するアイテムを取得していないaggregate関数を使用している場合、linqクエリが以下のような結果を与えていることを確認する必要があります。

var maxOrderLevel =sdv.Any()? sdv.Max(s => s.nOrderLevel):0
4
Ashwini

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

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

列が機能するには、列がNullable型である必要がありました。

var Dealer = Context.Dealers.Where(x => x.dealerCode ==ディーラーコード).FirstOrDefault();

ビューの更新前:

public int SubscriberId { get; set; }

ビューの更新後:

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

EDMXでのビューの削除と追加は正常に機能しました。

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

4
live-love

私はこのコードを使用していますが、正しく応答します。出力値のみが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
                            }
2
MohammadSoori

この質問にはすでに答えがあります。ただし、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
Lijo

実行時にこのコードを使用してEntity Framework 6でこのエラーを取得しました:

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

LeandroSoaresからの更新:

これを単一の実行に使用します。

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

オリジナル:

これに変更してから動作しました:

var fileEventsSum = db.ImportInformations.Any() ? db.ImportInformations.Sum(x => x.FileEvents) : 0;
0
Ogglas