Robię samouczek praktyczny mvcmusicstore. Zauważyłem coś podczas tworzenia rusztowania dla menedżera albumów (dodaj usuń edycję).
Chcę pisać kod elegancko, więc szukam przejrzystego sposobu, aby to napisać.
FYI, sprawiam, że sklep jest bardziej ogólny:
Albumy = elementy
Gatunki = Kategorie
Artysta = marka
Oto jak indeks jest pobierany (generowany przez MVC):
var items = db.Items.Include(i => i.Category).Include(i => i.Brand);
Oto jak jest pobierany element do usunięcia:
Item item = db.Items.Find(id);
Pierwsza z nich przywraca wszystkie elementy i zapełnia modele kategorii i marki w modelu przedmiotu. Drugi nie wypełnia kategorii i marki.
Jak mogę napisać drugą, aby znaleźć i zapełnić to, co jest w środku (najlepiej w 1 linii) ... teoretycznie - coś takiego:
Item item = db.Items.Find(id).Include(i => i.Category).Include(i => i.Brand);
c#
asp.net-mvc
entity-framework
Ralph N
źródło
źródło
Odpowiedzi:
Musisz
Include()
najpierw użyć , a następnie pobrać pojedynczy obiekt z wynikowego zapytania:źródło
Odpowiedź Dennisa to użycie
Include
iSingleOrDefault
. Ten ostatni przechodzi w obie strony do bazy danych.Alternatywą jest użycie
Find
, w połączeniu zLoad
, do jawnego ładowania powiązanych jednostek ...Poniżej przykład MSDN :
Oczywiście
Find
wraca natychmiast bez składania zapytania do sklepu, jeśli ten podmiot jest już załadowany przez kontekst.źródło
Find
więc, jeśli jednostka jest obecna, nie ma rundy do bazy danych dla samej jednostki. ALE, będziesz mieć podróż w obie strony dla każdego związku, z którym się łączyszLoad
, podczas gdySingleOrDefault
kombinacjaInclude
ładuje wszystko za jednym razem.Load
funkcję, relacja powinna zostać wypełniona po powrocie wywołania. Więc jeśli dzwoniszLoad
wiele razy dla wielu relacji, za każdym razem nastąpi podróż w obie strony. Nawet dla pojedynczej relacji, jeśliFind
metoda nie znajdzie jednostki w pamięci, wykonuje dwie rundy: jedną forFind
i drugą forLoad
. AleInclude
.SingleOrDefault
podejście wyszukuje byt i relację za jednym razem, o ile wiem (ale nie jestem pewien)Musisz rzucić IQueryable na DbSet
var dbSet = (DbSet<Item>) db.Set<Item>().Include("");
return dbSet.Find(id);
źródło
Nie działa dla mnie. Ale rozwiązałem to w ten sposób.
Nie wiem, czy to dobre rozwiązanie. Ale drugi, podany przez Dennisa, dał mi błąd bool
.SingleOrDefault(x => x.ItemId = id);
źródło
SingleOrDefault(x => x.ItemId = id)
tylko z powodu złego pojedynczego=
zamiast podwójnego==
?Nie ma naprawdę łatwego sposobu na filtrowanie za pomocą znalezienia. Ale wymyśliłem bliski sposób na odtworzenie funkcjonalności, ale proszę zwrócić uwagę na kilka rzeczy dotyczących mojego rozwiązania.
To rozwiązanie umożliwia filtrowanie ogólne bez znajomości klucza podstawowego w .net-core
Funkcja Find różni się zasadniczo, ponieważ uzyskuje jednostkę, jeśli jest ona obecna w śledzeniu przed wysłaniem zapytania do bazy danych.
Dodatkowo może filtrować według obiektu, dzięki czemu użytkownik nie musi znać klucza podstawowego.
To rozwiązanie jest przeznaczone dla EntityFramework Core.
Oto kilka metod rozszerzenia do dodania, które pomogą Ci filtrować według klucza podstawowego
Gdy masz już te metody rozszerzenia, możesz filtrować w ten sposób:
źródło