143

When creating a database using Entity Framework code-first, a lot of the database model is can be extracted from the code. Fluent API and/or Attributes can be used to fine-tune the model.

What are the advantages and disadvantages of Fluent API in comparison to Data Annotations? In other words, even if in certain situations both methods can be used, in what cases should one method prevail above the other?

blackraven
  • 5,284
  • 7
  • 19
  • 45
Sam
  • 15,336
  • 25
  • 85
  • 148
  • 3
    Just an idea: What I usually do is create a Model project with my POCOs, and then in the Repository project, create a new set of POCOs specifically for EF, and put my annotations there. Then I just map between the two in mapper classes. That way, my model stays untouched, and makes it easy to add to/change my data strategy, if necessary (e.g. add an XmlRepository and use the same Model classes). – adimauro Mar 27 '11 at 13:30
  • 1
    I now prefer Annotation, with EFCore and additional libraries. (requires less code, and all is in one place) https://github.com/isukces/EfCore.Shaman - add and extends attributes https://github.com/borisdj/EFCore.FluentApiToAnnotation - useful when DB already exist, after doing Reverse-Engineering and switching to CodeFirst – borisdj Jun 21 '17 at 09:17

1 Answers1

171

Everything what you can configure with DataAnnotations is also possible with the Fluent API. The reverse is not true. So, from the viewpoint of configuration options and flexibility the Fluent API is "better".

Configuration examples (for sure not a full list) which are possible in the Fluent API but not with DataAnnotations (as far as I can see):

  • Switch off cascading deletes:

    .WillCascadeOnDelete(false)

  • Specify foreign key column name in the database when the key isn't exposed in your object model:

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

  • Fine granular tuning of relationships, especially in all cases where only one side of an association is exposed in the object model:

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

  • Specification of inheritance mapping between object model and database tables (Table-Per-Hierarchy, Table-Per-Type, Table-Per-Concrete-Class):

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

Edit: Microsoft considers the Fluent API as an "advanced feature" (Quote from here):

The fluent API is considered a more advanced feature and we would recommend using Data Annotations unless your requirements require you to use the fluent API.

But in my opinion you reach the limitations of DataAnnotations very quickly (except perhaps for extremely simple object models). If you cannot fine tune your model with DataAnnotations anymore your last resort is to follow the default mapping conventions (by naming your properties according to those rules). Currently you cannot overwrite the conventions (only disable them; MS announced to give configuration options for the conventions in future EF releases). But if you don't want to be forced by the mapping conventions when you define your object model, your only option then is the Fluent API.

Learning the Fluent API is almost a Must imho, the DataAnnotations are a nice-to-have for simple applications.

Slauma
  • 175,098
  • 59
  • 401
  • 420
  • 2
    I am a newbie in this field. Can Fluent API be used to validate user interfaces as DataAnnotation can do? – kiss my armpit Jan 17 '12 at 09:18
  • 31
    @CounterTerrorist: I don't think so. For example: If you put the `[Required]` attribute on a property in an ASP.NET MVC application it will be used both by EF *and* by MVC for validation purposes because both can process this attribute. But MVC won't understand the Fluent API configuration. So, if you remove the attribute and use `HasRequired` in Fluent API instead, for EF it will be the same but not for MVC. (In my opinion the attributes should have been named differently, the usage of the DataAnnotations namespace from different components and for different purposes is very confusing.) – Slauma Jan 17 '12 at 11:20
  • 1
    OK. Thanks. I just tried it and the result is exactly the same as what you said. I hope the next MVC's validation can work with Fluent API. :) – kiss my armpit Jan 17 '12 at 11:25
  • 4
    Also note `[DefaultValue()]` isn't possible in Fluent Either. – webnoob Feb 08 '14 at 16:32
  • 4
    MinValue is an attribute that cannot be defined via Fluent API (Programming Entity Framework: Code First) (source: deleted NAA by [The Cog](https://stackoverflow.com/users/1036302/the-cog)) – Serge Ballesta Jul 08 '14 at 12:37
  • 12
    From a architectural point of view, I guess `Fluent API` would keep your implementation logic in your `DbContext` and keep your `POCO`s clean – Luke T O'Brien Mar 03 '17 at 12:34
  • 3
    Attributes have the advantage that every entity encapsulates each property's settings within that entity itself. Super clean to have .sql scripts formally design your database and reverse engineer class files with attributes; bypasses migrations too. – DeepSpace101 Jul 05 '18 at 21:05
  • 2
    @Slauma; for simple CRUD apps yes but technically you shouldn't expose your domain types to web frontend and have instead DTOs or MVC models where you should apply the attributes. – Jack0fshad0ws Feb 26 '20 at 20:55
  • I agree with you, Fluent API is much better, it has more features. – ayed abboushi Nov 22 '21 at 23:39
  • One of the best advantage of fluent syntax is `persistence ignorance`. Because with using EF attributes on our domain model, it leaks infrastructure concern on our domain model. We don’t want to have high coupling between our model and the persistence store. – Mehdi Hadeli Feb 27 '22 at 10:03
  • @Mehdi Hadeli, isn't this why you should always expose dto's for your application logic? I get why you want to use Fluid, but for me its jet another example of skipping the n-tier rules in favor of speed of development. Not saying it's wrong, but you are going to have problems when complexity increases, like when you need to query on a foreign key, which is hidden because of fluid. – ikwillem May 07 '22 at 06:12
  • Key information isn't hidden when using Fluent API. You use the metadata information provided through the EF apis. It is very discoverable at runtime. – long2know Jul 12 '22 at 21:19