web-dev-qa-db-fra.com

La conversion en type de valeur 'Int32' a échoué car la valeur matérialisée est null

J'ai le code suivant. Je reçois une erreur:

"La conversion en type de valeur 'Int32' a échoué car la valeur matérialisée est null. Le paramètre générique du type de résultat ou la requête doit utiliser un type nullable."

lorsque la table CreditHistory ne contient aucun enregistrement.

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

Comment puis-je modifier la requête pour accepter les valeurs NULL?

185
zosim

Une requête linq-to-sql n'est pas exécutée sous forme de code, mais traduite en SQL. Parfois, il s'agit d'une "abstraction qui fuit" qui donne un comportement inattendu.

Un de ces cas est la gestion des valeurs NULL, où il peut y avoir des valeurs NULL inattendues à différents endroits. ...DefaultIfEmpty(0).Sum(0) peut aider dans ce cas (assez simple), où il pourrait ne pas y avoir d'éléments et où SUM de SQL retournera null alors que c # s'attend à 0.

Une approche plus générale consiste à utiliser ?? qui sera traduit en COALESCE chaque fois que le SQL généré risque de renvoyer une valeur NULL inattendue:

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;

Cela lance d'abord int? pour indiquer au compilateur C # que cette expression peut en effet renvoyer null, même si Sum() renvoie un int. Nous utilisons ensuite l’opérateur normal ?? pour gérer le cas null.

Sur la base de cette réponse, j'ai écrit un article de blog avec des détails pour LINQ to SQL et LINQ to Entities.

317
Anders Abel

Pour autoriser un champ nullable Amount, il suffit d'utiliser l'opérateur de fusion nul pour convertir les valeurs nulles en 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

Vous utilisez la fonction aggregate qui ne nécessite pas que les éléments effectuent une action, vous devez vérifier que la requête linq donne un résultat comme ci-dessous:

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

Vous aviez ce message d'erreur lorsque j'essayais de sélectionner une vue.

Le problème était que la vue avait récemment gagné de nouvelles lignes nulles (dans la colonne SubscriberId) et qu’elle n’avait pas été mise à jour dans EDMX (base de données EF en premier).

La colonne devait être de type Nullable pour fonctionner.

var dealer = Context.Dealers.Where (x => x.dealerCode == dealerCode) .FirstOrDefault ();

Avant de rafraîchir la vue:

public int SubscriberId { get; set; }

Après le rafraîchissement de la vue:

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

La suppression et l'ajout de la vue dans EDMX ont fonctionné.

J'espère que ça aide quelqu'un.

4
live-love

J'ai utilisé ce code et il répond correctement, seule la valeur de sortie est nullable.

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
                            }
3
MohammadSoori

Je vois que cette question est déjà répondue. Mais si vous souhaitez le scinder en deux déclarations, les suivantes peuvent être considérées.

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

Vous avez cette erreur dans Entity Framework 6 avec ce code au moment de l'exécution:

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

Mise à jour de LeandroSoares:

Utilisez ceci pour une exécution unique:

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

Original:

Changé pour cela et puis ça a fonctionné:

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