Overriding Code-First conventions

by Sachin Singh


Posted on Wednesday, 20 January 2021

Tags: How to override code-first convention using data annotations and fluent api

In this section we will learn to override the code-first convention so your database would look exactly the same as you want. This is strictly required if you are working as a Database Administrator (DBA) who has strict requirements about the database schema.

Entity Framework is based on convention over configuration which means if you stick to the convention then you will need less configuration and your source code will be cleaner and more maintainable but if you don't like the convention that comes out of the box with EF then you can always override them.

There are two ways to override code-first conventions
    1. using data annotations.
    2. using Fluent API.

Data Annotations

Data Annotations attributes are .NET attributes which can be applied on an entity class or properties to override default conventions in Entity Framework.

Data annotation attributes are included in the System.ComponentModel.DataAnnotations and System.ComponentModel.DataAnnotations.Schema namespaces .These attributes are not only used in Entity Framework but they can also be used with ASP.NET MVC or data controls.

Find the below example on data annotations.


  public class Employee
    {   
       [Required]
       [MaxLength(50)]
       public string Name { get; set; }
       [Required]
       public int Age { get; set; }    
    }

Fluent API

In previous articles we used Data-Annotations to override code first conventions, Fluent API is another way to configure domain classes to override conventions. There is a design pattern called fluent design pattern where results are formulated by method chaining, one after another, The Entity Framework's Fluent API is based on that design pattern , as the method chaining thing looks like a flow (like river flowing in one direction) it is called as Fluent API.

In Entity Framework , the DbModelBuilder class acts as a Fluent API using which we can configure many different things. It provides far more options of configurations than Data Annotation attributes, so i always recommend Fluent API over data-annotations.

To write Fluent API configurations,we need to override the OnModelCreating() method of DbContext class context class, as shown below.


 public class OrganizationDbContext: DbContext 
   {
    public DbSet Employees { get; set; }      
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //Write Fluent API configurations here
           //ex shown below
                    modelBuilder.Entity()
                                .Property(x => x.Name)
                                .IsRequired();
                    base.OnModelCreating(modelBuilder);
    }
 }

Which Approach is better

Data Annotations are simple and require less code to override conventions, but they do not work well with complex business models and complex relationships between tables. There is one more issue with data annotation is that it fills our domain classes with database things, for example, a Required attribute over a property specifies that it is a not null column in the database, which is against the separation of concern principle, our domain model should be independent of the database not only because of separation of concern thing but also for better maintenance and Fluent API provides us both a separate place for configuration and better maintainability opportunity.

One thing I personally recommend to you is whichever approach you choose, just stick with that please don't mix both of them together, EF will not stop you mixing these approaches and obviously, you can apply data annotations to override some convention and Fluent API to override other convention at the same time, but it complicates your maintenance because every time you make changes you need to look at two places one is the class definition for data annotations and other is DbContext for Fluent API.

For small applications you should choose data annotations but for enterprise solutions always stick to Fluent API, it gives you better separation of concern and reduces maintenance cost.