2009-09-22 16 views
8

Myślę, że istnieje podobny post na ten temat, ale nie do końca taki sam ...Entity Framework - Dziedziczenie z .Include?

Mam dwa podmioty w moim modelu EF - nazwijmy je Person i Developer, przy czym ten ostatni dziedziczy po pierwszym.

Mam również stowarzyszenie na Deweloper nazwie Kwalifikacje. To nie jest widoczne w encji Osoba.

Jeśli piszę zapytanie dotyczące kontekstu, w jaki sposób automatycznie .Include() Kwalifikacje programisty, np.

od pracownika context.Employee .Include („kwalifikacje”) wybierz pracownik

nie działa ... EF narzeka, że ​​związek nie istnieje (zakładam, ponieważ nie istnieje na pracowniku - ale nie ma podmiotu programistycznego w kontekście, tylko pracownik).

Odpowiedz

0

Nie jestem zaznajomiony z EF, ale to wygląda mi na standardowy problem z dziedziczeniem. Jeśli chcesz uzyskać dostęp do unikalnych właściwości klasy potomnej z kolekcji "obiektów nadrzędnych" (gdzie rzeczywiste obiekty mogą lub nie mogą być instancjami klasy podrzędnej), musisz sprawdzić typ obiektu i rzucić go na dziecko w razie potrzeby możesz uzyskać dostęp do unikalnych właściwości.

Czego można się spodziewać, że dane oświadczenie zostanie zwrócone, jeśli niektóre lub wszystkie obiekty nie były danymi autora?

+0

Witam ... Nie należy próbować ładować elementów podrzędnych dla klasy bazowej, ponieważ nie istnieją. Wykonuję casting, aby sprawdzić właściwości podrzędnych itp. - ale cały punkt tego fragmentu to przeczytanie go za jednym razem (pamiętaj, że EF nie obsługuje leniwego ładowania). –

+0

Myślę, że byłbym skłonny do nie podklasy Osoba, ale raczej utworzyć inną klasę o nazwie Deweloper, który ma Osobę, w ten sposób można prawdopodobnie pobrać kolekcję osoby i poprzez stowarzyszenie być w stanie odzyskać te, które są przywoływane przez programistę i z tego obiektu programisty można znaleźć osoby z kwalifikacjami. Naprawdę nie jestem pewien, czy można zrobić to, co próbujesz zrobić, używając wskazanej przez ciebie hierarchii klas. – Lazarus

2

Jak o tym:

var results = from developer in ctx.Employee.OfType<Developer>() 
       select new {developer, Qualifications = developer.Qualifications}; 

rzeczy są interesujące tutaj:

  1. jesteśmy wyjątkiem pracowników, którzy nie są Deweloperzy
  2. jesteśmy wtedy wystające swoje kwalifikacje, jak i efekt uboczny tej projekcji, coś o nazwie fixup z wypełnieniem każdego developer.Qualifications też. To znaczy. to jest inny sposób uzyskania efektu takiego samego jak Include().

jeżeli następnie to zrobić:

var developers = from anon in developers.AsEnumerable() 
       select anon.Developer; 

Dostaniesz tylko programistów, a oni mają swoje kwalifikacje ładowane zbyt.

Zobacz Tip 1 uzyskać więcej informacji o tym, dlaczego to działa

Hope this helps

Alex

+0

Cześć - dzięki za sugestię. Wypróbuję to! Wygląda na to, że nie jest to "oficjalnie wspierane" rozwiązanie z tego linku, które podałeś. Zostałem tymczasowo obejrzany, wywołując polecenie Load w kolekcji podrzędnej, ale powoduje to oddzielne wywołanie SQL, więc bardzo chciałbym go ominąć, jeśli to możliwe. Jeszcze raz dziękuję. –

+1

Chociaż jedno, co właśnie sobie uświadomiłem - metoda, w której ten kod żyje, powinna być w stanie pracować zarówno z klasami pochodnymi, jak i innymi, tj. Powinienem odzyskać kolekcję pracowników, z których niektórzy mogą być programistami (którzy wówczas powinni mają wypełnione kwalifikacje). –

+1

Bit, który nie jest oficjalnie obsługiwany w łączu, był Sortowanie kolekcji. Faktyczne ładowanie kolekcji (wszystko, co jest używane powyżej) jest w pełni obsługiwane. –

10

Natknąłem tego problemu i eksperymentował trochę. Oto co znalazłem pracował z wykorzystaniem LINQ 2 Entity.

Powiedzmy, że mamy w twoim przykładzie Osobę < - Deweloper ---- Kwalifikacje.

Jeśli chcesz wybrać programistę z uwzględnionymi kwalifikacjami, zrobiłbyś to.

var dev = (from d in context.Persons.OfType<Developer> 
          .Include("Qualifications") 
      where d.ID == id 
      select d).FirstOfDefault(); 

Teraz powiedzmy, że mamy kolejny związek pomiędzy osoby i adres, możemy również zawierać adres do select również za pomocą LINQ 2 podmiot.

var dev = (from d in context.Persons 
          .Include("Address") 
          .OfType<Developer>() 
          .Include("Qualifications") 
      where d.ID == id 
      select d).FirstOfDefault(); 

Wskazówki jak mam włączone rzeczy, które potrzebne zanim nawrócił Rodzaj i również ponownie po konwersji. Oba elementy powinny teraz współpracować bez żadnych problemów. Przetestowałem te metody i obie działają. Mam nadzieję, że będą pracować dla ciebie, biorąc pod uwagę, że prawidłowo skonfigurowałeś dziedziczenie.

GL.

2

podstawie odpowiedzi Tri Q, ale dla tych, które preferują podejście '.load()', można użyć:

context.Persons.OfType<Developer>().Include(t => t.Qualifications).Load(); 

używam go w moim DbContext. Stworzyłem metodę LoadDb(), która ładuje wszystkie potrzebne dane. Mogę więc używać go z wielu projektów.