17

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

enter image description here

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 .:

enter image description here

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.

+1

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

+0

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? –

+0

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

Odpowiedz

1

Ja osobiście trzymam się bazy danych, gdy używam EF w każdym schemacie, który jest na tym poziomie złożoności. Miałem problemy ze złożonymi schematami w odniesieniu do kodu pierwszego. Być może nowsze wersje są trochę lepsze, ale martwienie się, jak próbować kodować skomplikowane relacje wydaje się mniej proste, pozwalając silnikowi na wygenerowanie go dla ciebie. Również, gdy związek dostaje ten kompleks, staram się unikać próbowania generowania go za pomocą EF i próbować używać procedur przechowywanych, aby łatwiej rozwiązywać problemy z wąskimi gardłami, które mogą się pojawić.

+0

W końcu doszedłem do wniosku, że muszę iść tą drogą. Chodzi o to, że model edmx pozwala na wprowadzanie zmian w modelu koncepcyjnym, podczas gdy kod-pierwszy nie oferuje żadnych narzędzi do tego rozróżnienia. Z pierwszym kodem wszystkie konfiguracje odwzorowania w równym stopniu wchodzą do modelu sklepu i modelu koncepcyjnego. Obawiam się, że zespół EF nie jest zainteresowany opracowaniem narzędzi do kształtowania tylko modelu koncepcyjnego (poza modelem sklepu) w pierwszym API kodu. –

+0

Powodzenia w przyszłości, MS wyciągnął wtyczkę na wsparcie edmx ... http://www.theregister.co.uk/2014/10/23/entity_framework_goes_codefirst_only_as_microsoft_shutters_yet_another_visual_modelling_tool/ –