Dereference de un eventual referință nulă în Entity Framework 6 interogare

0

Problema

Am un .NET 6 proiect cu null tipuri de referință activat (<Nullable>enable</Nullable>). Am acest EF entitate:

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

Am adăugat ? de mai sus pentru a preveni acest lucru poate fi nul de avertizare:

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

Acum, am acest Entity Framework 6 LINQ interogare:

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

... dar am obține următorul avertisment:

Dereference of a possibly null reference.

... pe partea asta a mea de interogare:

x.User.Id == ...

Cum pot rezolva acest avertisment?

4

Cel mai bun răspuns

2

Cred că vrei să spui ceva de genul:

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

Original problemă este un avertisment că C#8 introdus cu a fi mai explicit cu null-capabil tipuri de referință. Pentru o entitate, mai sus de implementare nu este valabilă decât dacă aceste relații sunt, într-adevăr, opțional, care ar necesita lor FK câmpuri (nume de Utilizator și PostId) să fie, de asemenea, Null-capabil. Ei probabil sunt nu optional.

Principalele opțiuni pentru a adresa aceasta:

A) a dezactiva caracteristica. (Dezactivare null-capabil de referințe în proiect)

B) Cere "iertare" pentru faptul că acestea nu ar trebui să fie nulă, dar nu va fi într-un valabilă de stat în construcții. (EF le va gestiona)

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

Modificarea model pentru a marca navigare proprietăți ca nul-capabil de trimiteri este de natură să provoace tot felul de probleme ca cu migrații se poate, și va începe înlocuirea non-null-capabil FKs cu null-capabil de cei dragi. Pentru a marca aceste referințe ca Nul-capabil și să păstreze EF fericit:

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

Care este, aproape sigur, nu ceea ce vrei în domeniu, sau chiar juridice dacă UserId și PostId fac parte dintr-un PK.

Personal am să marchez această schimbare în C# ca un "teren minat" MS activat inițial în mod implicit, cum ar fi Partea de Client de Evaluare în EF. :) Prevăd multe-o-StackOverflow întrebări în jurul valorii de acest avertisment sau rupere modificări, și multe-un-client codebases presărat cu "!" iertare tag-uri vechi, non-null-capabil de obiecte/referințe sunt trecute în codul cu null-capabil de referință controale.

2021-11-24 23:15:24
1

Tu ar trebui să marcheze de navigare entități ca poate fi nul. Tu ar trebui să nu fi leneș încărcare activată, și, prin urmare, navigare proprietăți pot fi returnate ca null din interogări. Chiar dacă acestea sunt necesare în baza de date, codul nu trebuie să le încarce.

În expresii de interogare, puteți fi sigur că Entity Framework nu este de gând să le execute clientside, dar analiza o interogare SQL din ele.

Prin urmare:

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

Vă pot spune compilatorului cu User! că știi că nu va fi null acolo. Dacă activați clientside de evaluare, dar nu ar trebui, și dacă o faci, vei avea nevoie de un null check-acolo, oricum.

Cum pentru utilizare de PostFile.User, ca în:

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

Nu poate fi null dacă nu Include(p => p.User) și nu fi leneș încărcare activată, astfel încât user ar avea nevoie de un null verificați înainte de utilizare.

Dacă face uz de încărcare leneș, puteți dezactiva avertismentul:

#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

Cred că ai nevoie de asta:

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

Și de apel

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

Nr. Nu marchează aceste proprietăți ca poate fi nul face compilatorul emit avertismente că acestea nu ar putea fi inițializat, ceea ce este adevărat.
CodeCaster
0

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

2021-11-24 22:53:01

În alte limbi

Această pagină este în alte limbi

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