Entity Framework Code First - Zalety i wady interfejsu Fluent API w porównaniu z adnotacjami danych [zamknięte]

120

Podczas tworzenia bazy danych przy użyciu kodu Entity Framework można wyodrębnić wiele modeli bazy danych z kodu. Do dostrojenia modelu można użyć Fluent API i / lub Attributes.

Jakie są zalety i wady Fluent Api w porównaniu z adnotacjami danych? Innymi słowy: nawet jeśli w pewnych sytuacjach można zastosować obie metody, w jakich przypadkach jedna metoda powinna mieć pierwszeństwo przed drugą?

Sam
źródło
3
Pomysł: Zwykle tworzę projekt modelu z moimi POCO, a następnie w projekcie Repozytorium tworzę nowy zestaw POCO specjalnie dla EF i umieszczam tam moje adnotacje. Następnie po prostu mapuję między nimi w klasach mapperów. W ten sposób mój model pozostaje nietknięty i ułatwia dodawanie / zmianę strategii danych, jeśli to konieczne (np. Dodanie XmlRepository i użycie tych samych klas Model).
adimauro
1
Teraz wolę Adnotacje z EFCore i dodatkowymi bibliotekami. (wymaga mniej kodu, a wszystko jest w jednym miejscu) github.com/isukces/EfCore.Shaman - dodaje i rozszerza atrybuty github.com/borisdj/EFCore.FluentApiToAnnotation - przydatne, gdy DB już istnieje, po wykonaniu inżynierii odwrotnej i przejściu na CodeFirst
borisdj

Odpowiedzi:

142

Wszystko, co możesz skonfigurować za pomocą DataAnnotations, jest również możliwe dzięki Fluent API. Odwrotna sytuacja nie jest prawdą. Tak więc z punktu widzenia opcji konfiguracyjnych i elastyczności Fluent API jest „lepsze”.

Przykłady konfiguracji (na pewno nie pełna lista), które są możliwe w Fluent API, ale nie z DataAnnotations (o ile widzę):

  • Wyłącz usuwanie kaskadowe:

    .WillCascadeOnDelete(false)

  • Określ nazwę kolumny klucza obcego w bazie danych, gdy klucz nie jest ujawniony w modelu obiektów:

    .Map(conf => conf.MapKey("MyForeignKeyID"))

  • Precyzyjne dostrajanie relacji, zwłaszcza we wszystkich przypadkach, w których tylko jedna strona powiązania jest widoczna w modelu obiektowym:

    .WithMany(...), WithOptional(...), WithRequiredDependent(...),WithRequiredPrincipal(...)

  • Specyfikacja mapowania dziedziczenia między modelem obiektu a tabelami bazy danych (Table-Per-Hierarchy, Table-Per-Type, Table-Per-Concrete-Class):

    .Map<TDerived>(Action<EntityMappingConfiguration<TDerived>> ...)

Edycja: Microsoft uważa Fluent API za „funkcję zaawansowaną” (cytat z tego miejsca ):

Interfejs API Fluent jest uważany za bardziej zaawansowaną funkcję i zalecamy korzystanie z adnotacji danych, chyba że Twoje wymagania wymagają korzystania z interfejsu Fluent API.

Ale moim zdaniem bardzo szybko osiągasz ograniczenia DataAnnotations (z wyjątkiem być może bardzo prostych modeli obiektowych). Jeśli nie możesz już dostroić swojego modelu za pomocą adnotacji danych, ostatnią deską ratunku jest przestrzeganie domyślnych konwencji mapowania (poprzez nadawanie nazw właściwościom zgodnie z tymi regułami). Obecnie nie można nadpisać konwencji (tylko je wyłączyć; firma MS ogłosiła, że ​​poda opcje konfiguracji dla konwencji w przyszłych wersjach EF). Ale jeśli nie chcesz być zmuszony przez konwencje mapowania podczas definiowania modelu obiektów, jedyną opcją jest interfejs API Fluent.

Nauka interfejsu Fluent API jest prawie koniecznością, adnotacje DataAnnotations są przydatne w przypadku prostych aplikacji.

Slauma
źródło
2
Jestem nowicjuszem w tej dziedzinie. Czy Fluent API może służyć do sprawdzania poprawności interfejsów użytkownika, tak jak może to zrobić DataAnnotation?
pocałuj mnie pod pachę
27
@CounterTerrorist: Nie sądzę. Na przykład: jeśli umieścisz [Required]atrybut we właściwości w aplikacji ASP.NET MVC, będzie on używany zarówno przez EF, jak i przez MVC do celów walidacji, ponieważ oba mogą przetwarzać ten atrybut. Ale MVC nie zrozumie konfiguracji Fluent API. Tak więc, jeśli usuniesz atrybut i HasRequiredzamiast tego użyjesz go w interfejsie Fluent API, dla EF będzie to takie samo, ale nie dla MVC. (Moim zdaniem atrybuty powinny być nazwane inaczej, użycie przestrzeni nazw DataAnnotations z różnych komponentów i do różnych celów jest bardzo zagmatwane.)
Slauma
4
Uwaga również [DefaultValue()]nie jest możliwa w przypadku Fluent Either.
webnoob,
4
MinValue to atrybut, którego nie można zdefiniować za pomocą Fluent API (Programming Entity Framework: Code First) (źródło: usunięte NAA przez The Cog )
Serge Ballesta
7
Chyba z architektonicznego punktu widzenia Fluent API że zachowałbym logikę implementacji w Twoim DbContexti POCOczystym
Luke T O'Brien