Déréférencement d'une référence null dans Entity Framework 6 de la requête

0

La question

J'ai un .NET 6 du projet avec les valeurs null de référence types de permis (<Nullable>enable</Nullable>). J'ai cet EF entité:

public class PostFile {
  public Int32 UserId { get; set; }
  public Int32 PostId { get; set; }

  public virtual User? User { get; set; }
  public virtual Post? Post { get; set; }
}

J'ai ajouté ? ci-dessus pour éviter ce nullable avertissement:

Non-nullable property '...' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

Maintenant, j'ai ce Entity Framework 6 requête LINQ:

var postFiles = context.postFiles.Where(x => x.User.Id == request.UserId);

... mais je reçois le message d'avertissement suivant:

Dereference of a possibly null reference.

... sur cette partie de ma requête:

x.User.Id == ...

Comment puis-je corriger cet avertissement?

4

La meilleure réponse

2

Je pense que vous voulez dire quelque chose comme:

public class PostFile {
    public Int32 UserId{ get; set; }
    public Int32 PostId { get; set; }

    public virtual User? User { get; set; }
    public virtual Post? Post { get; set; }
}

Votre problème d'origine est un avertissement que le C#8 introduit à être plus explicite avec null en mesure de types de référence. Pour une entité, la mise en œuvre n'est pas valide à moins que ces relations sont en effet en option, ce qui nécessiterait leur FK champs (nom d'utilisateur et PostId) d'être aussi Nulle-mesure. Il est probable qu'ils sont pas en option.

Les principales options à cette adresse:

A) désactiver la fonctionnalité. (Désactiver null capable de références dans le projet)

B) de Demander "pardon" pour le fait qu'ils ne doivent jamais être nulle, mais ne sera pas dans un état valide la construction. (EF gérer)

public class PostFile {
    public Int32 UserId{ get; set; }
    public Int32 PostId { get; set; }

    public virtual User User { get; set; } = null!;
    public virtual Post Post { get; set; } = null!;
}

Modifier le modèle pour marquer les propriétés de navigation comme nulle capable de références est susceptible de causer toutes sortes de problèmes avec les migrations il peut et va commencer à remplacer en mesure non null FKs avec null-mesure ceux. Pour marquer ces références comme Nulle et garder EF heureux:

public class PostFile {
    public Int32? UserId{ get; set; }
    public Int32? PostId { get; set; }

    public virtual User? User { get; set; }
    public virtual Post? Post { get; set; }
}

Ce qui est presque certainement pas ce que vous voulez dans votre domaine, ou même si un nom d'utilisateur et PostId font partie d'un PK.

Personnellement, je suis farinage ce changement en C# comme un "champ de mines" MS initialement activé par défaut, tels que Côté Client, l'Évaluation de l'EF. :) Je prévois d'une StackOverflow questions autour de cet avertissement ou de la rupture de changements, et beaucoup d'-un-client code parsemé de "!" le pardon des balises que les anciens non-null-mesure d'objets/références sont transmis dans le code avec la valeur null en mesure de vérification des références.

2021-11-24 23:15:24
1

Vous devez marquer de navigation entités comme nullable. Vous ne devriez pas avoir un chargement différé activé, et donc les propriétés de navigation peuvent être retournés comme null à partir de requêtes. Même si elles sont nécessaires dans la base de données, votre code n'a pas à les charger.

Dans vos expressions de requête, vous pouvez être certain que Entity Framework ne va pas exécuter côté client, mais d'analyser une requête SQL d'eux.

Donc:

.Where(x => x.User!.Id == request.UserId)

Vous pouvez indiquer au compilateur avec User! que vous savez qu'il ne sera pas null. Sauf si vous activez le client de l'évaluation, mais vous ne devriez pas, et si vous le faites, vous aurez besoin d'un nul vérifier de toute façon.

Comme pour l'utilisation de PostFile.Usercomme dans:

var postFile = dbContext.PostFiles.FirstOrDefault(p => p....) ?? throw ...;
var user = postFile.User;

Là, il peut être null si vous n'avez pas Include(p => p.User) et n'ont pas de chargement différé activé, de sorte que user aurait besoin d'un nul vérifier avant l'utilisation.

Si vous n' utilisez chargement paresseux, vous pouvez désactiver l'avertissement:

#pragma warning disable CS8618 // EF initializes these properties through lazy loading
    public virtual User User { get; set; }
#pragma warning restore CS8618 
2021-11-24 22:37:30
0

Je pense que vous avez besoin de ceci:

public class PostFile {
    public User User { get; set; }
    public Post Post { get; set; }
}

Et appel

var postFiles = context.postFiles.Where(x => x.User.Id == request.UserId).Include(x => x.Post);
2021-11-24 22:52:47

Pas de. Pas de marquage de ces propriétés comme nullable fait le compilateur émettent des mises en garde qu'ils ne pourraient pas être initialisé, ce qui est vrai.
CodeCaster
0

Ce sujet var postFiles = context.postFiles.Where(x => x.User != null && x.User.Id == request.UserId);?

2021-11-24 22:53:01

Dans d'autres langues

Cette page est dans d'autres langues

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................