Entity Framework 6 sorgusunda muhtemelen boş bir başvurunun dereferansı

0

Soru

Geçersiz başvuru türleri etkinleştirilmiş bir. NET 6 projem var (<Nullable>enable</Nullable>). Bu EF varlığım var:

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

Ekledim ? bu geçersiz uyarıyı önlemek için yukarıda:

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

Şimdi, bu Entity Framework 6 LINQ sorgum var:

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

... ama şu uyarıyı alıyorum:

Dereference of a possibly null reference.

... sorgumun bu bölümünde:

x.User.Id == ...

Bu uyarıyı nasıl düzeltebilirim?

4

En iyi cevabı

2

Sanırım şöyle bir şey demek istiyorsun:

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

Asıl sorununuz, C # 8'in boş referans türleriyle daha açık olmasıyla ortaya çıkan bir uyarıdır. Bir varlık için, bu ilişkiler gerçekten isteğe bağlı olmadıkça, FK alanlarının (UserId ve PostId) da Boş olmasını gerektiren yukarıdaki uygulama geçerli değildir. Muhtemelen isteğe bağlı değildirler.

Bunu ele almak için ana seçenekler:

A) Özelliği kapatın. (Projedeki boş başvuruları devre dışı bırak)

B) Bunların asla boş olmaması gerektiği, ancak inşaatta geçerli bir durumda olmayacağı için "af" dileyin. (EF onları yönetecek)

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

Gezinme özelliklerini null-able başvuruları olarak işaretlemek için modeli değiştirmek, geçişlerde olduğu gibi her türlü soruna neden olabilir ve null-able olmayan FK'LERİ null-able olanlarla değiştirmeye başlar. Bu referansları Null olarak işaretlemek ve ef'yi mutlu etmek:

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

Kullanıcı kimliği ve PostId bir pk'nin parçasıysa, etki alanınızda neredeyse kesinlikle istediğiniz şey değildir, hatta yasaldır.

Şahsen, C# ' daki bu değişikliği, ef'deki İstemci Tarafı Değerlendirmesi gibi başlangıçta varsayılan olarak etkinleştirilmiş bir "kara mayını" MS olarak yazıyorum. :) Bu uyarı veya kırılma değişiklikleriyle ilgili birçok-a-StackOverflow sorusu ve"!"eski boş olmayan nesneler/referanslar olarak bağışlama etiketleri, boş olan referans kontrolleriyle koda geçirilir.

2021-11-24 23:15:24
1

Gezinme varlıklarını geçersiz olarak işaretlemelisiniz. Tembel yüklemeyi etkinleştirmemelisiniz ve bu nedenle gezinme özellikleri şu şekilde döndürülebilir: null sorgulardan. Veritabanında gerekli olsalar bile, kodunuzun bunları yüklemesi gerekmez.

Sorgu ifadelerinizde, Entity Framework'ün bunları istemci tarafında yürütmeyeceğinden, ancak bunlardan bir SQL sorgusunu ayrıştırmayacağından emin olabilirsiniz.

Bu nedenle:

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

Derleyiciye şunları söyleyebilirsiniz User! orada boş olmayacağını bildiğini. Müşteri tarafı değerlendirmesini etkinleştirmediğiniz sürece, ancak yapmamalısınız ve eğer yaparsanız, yine de orada boş bir kontrole ihtiyacınız olacaktır.

İçin kullanımı PostFile.User gibi :

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

Orada olabilir null eğer yapmadıysan Include(p => p.User) ve tembel yükleme etkin değil, bu yüzden user kullanmadan önce boş bir kontrol gerekir.

Tembel yükleme kullanıyorsanız, uyarıyı devre dışı bırakabilirsiniz:

#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

Bence buna ihtiyacın var.:

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

Ve ara

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

Hayır. Null olarak bu özellikleri işaretleme derleyici doğru olan başlatıldı, olmayabilir bu uyarıları göster yapar.
CodeCaster
0

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

2021-11-24 22:53:01

Diğer dillerde

Bu sayfa diğer dillerde

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