Riferimento di un eventuale riferimento null in Entity Framework 6 query

0

Domanda

Ho una .NETTO 6 progetto con nullable tipi di riferimento abilitato (<Nullable>enable</Nullable>). Ho questo 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; }
}

Ho aggiunto ? sopra per evitare che questo nullable avviso:

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

Ora, ho questo Entity Framework 6 query LINQ:

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

... ma mi da il seguente avviso:

Dereference of a possibly null reference.

... su questa parte della mia query:

x.User.Id == ...

Come posso correggere questo errore?

4

Migliore risposta

2

Penso che tu intenda qualcosa di simile:

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; }
}

Il problema originale è un avvertimento che il C#8 ha introdotto con l'essere più esplicito con null-in grado i tipi di riferimento. Per un'entità, l'implementazione precedente non è valida, a meno che queste relazioni sono, infatti, opzionale, che richiedono il loro FK campi (UserId e PostId) per essere Null-in grado. Si è probabile che non opzionale.

Le principali opzioni per risolvere questo:

A) disattivare la funzione. (Disabilitare null-in grado i riferimenti del progetto)

B) Chiedere "perdono" per il fatto che questi non dovrebbero mai essere nullo, ma non sarà in uno stato valido per la costruzione. (EF sarà la loro gestione)

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!;
}

Alterare il modello di marchio di proprietà di navigazione come null-in grado di riferimenti è probabile che a causare tutti i tipi di problemi con le migrazioni è possibile iniziare a sostituire i non-null in grado FKs con null-capaci. Per contrassegnare questi riferimenti come Null in grado di mantenere EF felice:

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; }
}

Che è quasi certamente non quello che vuoi nel tuo dominio, o anche legale, se UserId e PostId sono parte di un PK.

Personalmente sto sfarinamento questo cambiamento in C# come una "terra mia" di MS inizialmente abilitata per impostazione predefinita, come il Lato Client di Valutazione in EF. :) Prevedo molti-a-StackOverflow domande intorno a questo avviso o di modifiche di rilievo, e molti-a-client basi di codice disseminato con "!" perdono di tag per anziani non-null in grado di oggetti/riferimenti sono passati in codice con null-in grado di riferimento per i controlli.

2021-11-24 23:15:24
1

Si dovrebbe segnare la navigazione entità come nullable. Non è necessario il caricamento pigro abilitato, e quindi le proprietà di navigazione possono essere restituiti null dalla query. Anche se sono necessari nel database, il tuo codice non sono a carico loro.

Per la tua ricerca di espressioni, si può essere certi che Entity Framework non sta andando per la loro esecuzione è, ma analizzare una query SQL di loro.

Quindi:

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

Si può dire che il compilatore con User! che si sa non essere null. A meno che non si attiva clientside di valutazione, ma non si deve, e se lo fate, avrete bisogno di un controllo null c'è comunque.

Come per l'utilizzo di PostFile.Usercome in:

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

Non ci può essere null se non Include(p => p.User) e non hanno il lazy loading abilitato, in modo da user avrebbe bisogno di un null controllare prima dell'uso.

Se si fanno uso di caricamento pigro, è possibile disattivare l'avviso:

#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

Penso che avete bisogno di questo:

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

E chiamata

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

No. Non marcatura queste proprietà come nullable consente al compilatore di emettere avvisi che potrebbero non essere inizializzato, che è vero.
CodeCaster
0

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

2021-11-24 22:53:01

In altre lingue

Questa pagina è in altre lingue

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