Mamy bazę danych, w której jedna tabela zawiera wpisy, które mogą być potomkami kilku innych tabel. Ma "miękki" klucz obcy składający się z ID właściciela i nazwy tabeli. Ten (anty) wzór jest znany jako "stowarzyszenia polimorficzne". Wiemy, że nie jest to najlepszy projekt bazy danych w historii, a zmienimy go w odpowiednim czasie, ale nie w najbliższej przyszłości. Pokażę uproszczony przykład:Modelowanie bazy polimorficznych skojarzeń - najpierw z kodem pierwszej
Zarówno Event
, Person
i Product
mieć rekordy W komentarzu. Jak widać, nie ma twardych ograniczeń FK.
W Entity Framework możliwe jest wspieranie tego modelu przez sublassing Comment
do EventComment
itp i niech Event
mieć EventComments
kolekcję itd .:
podklas i stowarzyszenia są dodawane ręcznie po generowanie podstawowego modelu z bazy danych. OwnerCode
jest dyskryminatorem w tym modelu TPH. Należy pamiętać, że Event
, Person
i Product
to zupełnie inne podmioty. Nie ma sensu posiadanie dla nich wspólnej klasy bazowej.
To jest baza danych na pierwszym miejscu. Nasz rzeczywisty model działa tak, nie ma problemu.
OK. Teraz chcemy przejść na kod-pierwszy. Więc zacząłem od odwrotnej inżynierii bazy danych do pierwszego modelu kodu (EF Power Tools) i kontynuowałem tworzenie podklas i mapowanie powiązań i dziedziczenia. Próbowałem połączyć się z modelem w Linqpad. Wtedy zaczęły się kłopoty.
Podczas próby wykonania kwerendy z tego modelu zgłasza InvalidOperationExeception
Komponent klucza obcego „ownerid” nie jest zadeklarowana właściwość typu „EventComment”. Sprawdź, czy nie została jawnie wykluczona z modelu i czy jest poprawną właściwością pierwotną.
Dzieje się tak, gdy mam powiązania dwukierunkowe i OwnerId
jest mapowany jako właściwość w Comment
. Odwzorowanie w moim EventMap
klasy (EntityTypeConfiguration<Event>
) wygląda następująco:
this.HasMany(x => x.Comments).WithRequired(c => c.Event)
.HasForeignKey(c => c.OwnerId);
Więc starałem się odwzorować stowarzyszenie bez OwnerId
w modelu
this.HasMany(x => x.Comments).WithRequired().Map(m => m.MapKey("OwnerId"));
To rzuca się MetaDataException
Określony schemat jest niepoprawny. Błędy: (10,6): error 0019: Każda nazwa właściwości w typie musi być unikalna. Nazwa właściwości "OwnerId" została już zdefiniowana. (11,6): error 0019: Każda nazwa właściwości w typie musi być unikalna. Nazwa właściwości "OwnerId" została już zdefiniowana.
Jeśli usuniemy dwa z trzech skojarzeń z komentarzem podmiotu, jest to w porządku, ale oczywiście to nie jest lekarstwo.
Niektóre szczegóły:
- Możliwe jest stworzenie działającego modelu DbContext („Kod sekund”) od edmx dodając element generatora DbContext. (na razie byłoby to możliwe).
- Kiedy eksportuję działający pierwszy model kodu (z jednym powiązaniem) do edmx (
EdmxWriter
), skojarzenie wydaje się być w modelu przechowywania, podczas gdy w oryginalnym edmx jest częścią modelu koncepcyjnego.
Jak zatem utworzyć ten kod modelu? Myślę, że kluczem jest, jak poinstruować najpierw kodowanie skojarzeń w modelu pojęciowym, a nie w modelu pamięci masowej.
Czy kiedykolwiek dostałeś model do pracy z Code-First? Ciekawe, że działa dla Db-First/EDMX. Miałem pytanie dotyczące podobnego modelu, a ostatnie słowo z CodePlex było zasadniczo "nieobsługiwane" i "podstawowe ograniczenie EF" (http://stackoverflow.com/a/14880084/270591). Ale jeśli twój model działa z EDMX, wydaje się, że jest to ograniczenie Code-First, a nie ogólne ograniczenie EF. – Slauma
Tak, działa pierwszy model bazy danych (dzięki Bogu). Prawdziwy model jest nawet b, bardziej złożony, ponieważ ma kompozytowe dyskryminatory dziedziczenia. Nie ma problemu. Kod pierwszy to problem. Czy kiedykolwiek próbowałeś swojego modelu db-first? –
Nie, nigdy tego nie próbowałem. Wiemy, że Code-First nie obsługuje wszystkich funkcji edmx, ale naprawdę nie oczekiwałem różnicy w tej sytuacji. Właśnie prosiłem o potwierdzenie w tym starym numerze na CodePlex (https://entityframework.codeplex.com/workitem/865, ostatni komentarz na stronie). Nie jestem pewien, czy mogę oczekiwać odpowiedzi w zamkniętej pozycji. – Slauma