Cofając ewentualnej zero linki w zapytaniu Entity Framework 6

0

Pytanie

Mam projekt .NET 6 z włączonymi typami linków z możliwością zerowania (<Nullable>enable</Nullable>). Mam ta istota EF:

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

Dodałem ? powyżej, aby temu zapobiec nieskuteczny ostrzeżenie:

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

Teraz mam ten zapytanie LINQ Entity Framework 6:

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

... ale otrzymuję następujący komunikat:

Dereference of a possibly null reference.

... w tej części mojego zapytania:

x.User.Id == ...

Jak mogę naprawić to ostrzeżenie?

4

Najlepsza odpowiedź

2

Myślę, że masz na myśli coś takiego:

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

Oryginalny problem-to ostrzeżenie o tym, że w C#8 wprowadzono bardziej precyzyjne określanie typów linków z zerową możliwością. Dla encji powyższa implementacja jest nie do zaakceptowania, jeśli tylko ten związek naprawdę nie są opcjonalne, co będzie wymagać, aby ich pola FK (identyfikator użytkownika i identyfikator postu) również były puste. Najprawdopodobniej nie są one opcjonalne.

Podstawowe opcje rozwiązania tego problemu:

A) Wyłącz tę funkcję. (Wyłącz zerowe linki w projekcie)

B) Poproś "przepraszam" za to, że nigdy nie powinno być zero, ale nie będą znajdować się w rzeczywistym stanie przy budowie. (EF będzie nimi zarządzać)

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

Zmiana modelu do oznaczania właściwości nawigacji jak linki, które zezwalają na zero, może powodować różnego rodzaju problemy, jak i podczas migracji, i zacznie wymieniać niezerowe FK na zero-zdolne. Aby uczcić te linki jako nieprawidłowe i zrobić EF szczęśliwy:

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

Że prawie na pewno nie to, co chcesz w swojej domenie, lub nawet legalne, jeśli identyfikator użytkownika i identyfikator postID są częścią KOMPUTERA.

Osobiście zaznaczam to zmiana w C# jak "minę" MS, początkowo który jest domyślnie włączony, na przykład, ocenę po stronie klienta w EF. :) Przewiduję wiele pytań StackOverflow, związanych z tym ostrzeżeniem lub krytyczne zmianami, i wiele klienckich kodowych baz, usiany tagiem przebaczenie"!", ponieważ stare obiekty/linki, nie zdolne do zera, są przekazywane w kod z walidacji linków na zero.

2021-11-24 23:15:24
1

Należy zaznaczyć pozycje nawigacji jak обнуляемые. U ciebie nie musi być włączona lazy loading, a więc właściwości nawigacji mogą być zwrócone jak null z zapytań. Nawet jeśli są one wymagane w bazie danych, do twojego kodu nie trzeba ich pobierać.

W wyrażeniach twoich wymagań, możesz być pewien, że Entity Framework nie będzie wykonywać ich na stronie klienta, a analizuje zapytania SQL na ich podstawie.

Zatem:

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

Możesz poinformować kompilator za pomocą User! że wiesz, że tam nie będzie równa zero. Jeśli nie włączyć ocenę po stronie klienta, ale nie powinno się tego robić, a jeśli to zrobisz, będziesz nadal potrzebował test na zero.

Co do użycia PostFile.Userjak w:

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

Tam to może być null gdyby tego nie zrobili Include(p => p.User) i nie włączaj leniwą pobieranie, więc user przed użyciem konieczne jest sprawdzenie na zero.

Jeśli korzystasz z opóźnioną, pobieranie, możesz wyłączyć ostrzeżenie:

#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

Myślę, że jest ci to potrzebne:

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

I zadzwoń

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

Nie. Jeśli te właściwości nie są oznaczone jako обнуляемые, kompilator generuje ostrzeżenia o tym, że mogą one nie być inicjowane, że to prawda.
CodeCaster
0

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

2021-11-24 22:53:01

W innych językach

Ta strona jest w innych językach

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