Overriding Code-First convention using Fluent API

by Sachin Singh


Posted on Thursday, 21 January 2021

Tags: Overriding Code-First convention using Fluent API Fluent API

Similar to Data Annotations, Entity Framework Fluent API is used to configure domain classes to override conventions. EF Fluent API is based on the fluent interface design pattern where the result is formulated by method chaining , 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 multiple things. Fluent API provides us more configuration options than Data-Annotations , so it is always recommened to use Fluent APi over data-annotations.

To write Fluent API configurations, we override the OnModelCreating() method of DbContextclass, as shown below.


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

     }
  }

Configure table name

By Default table names are plural form of your class name, if you want to override this convention then use ToTable() helper extension method as shown below.


  public class OrganizationDbContext: DbContext 
  {
    public DbSet<Employee> Employees { get; set; }
        
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //Write Fluent API configurations here
           //ex shown below
                    modelBuilder.Entity<Employee>()
                                          .ToTable(“tbl_Course”, “Organization”);

                    base.OnModelCreating(modelBuilder);

        }
    }

Configure primary Keys

By default the property named as Id or {ClassName}Id is considered as primary key , but sometimes you may want to make other column which neither ends with the word Id nor named as Id , then you can use HasKey() helper extension method . By default primary keys are considered as Identity if you want to override this convention you can use HasDatabaseGeneratedOption() helper extension method as shown below.


    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {       
           modelBuilder.Entity<Book>
                                 .HasKey(t=>t.Isbn);
                                 .Entity<Book>.Property(t=>t.Isbn)
                                 .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

    }

Configure Composite Primary Keys

To specify composite keys you can use HasKey() helper method with anonymous object as shown below.


   protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //Configure Column
    modelBuilder.Entity<OrderItem>
                         .HasKey(t =>new{t.OrderId, t.OrderItemId  });
    }

Configure Column Name, Type and Order

Entity Framework creates column with the same name, order and data type as specified in the Entity, You can override this convention, as shown below.


  public class OrganizationDbContext: DbContext 
   {

    public DbSet<Employee> Employees { get; set; }
        
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
         {
        //Configure Column
        modelBuilder.Entity<Employee>()
                              .Property(p => p.Name)
                              .HasColumnName("Emp_Name")
                              .HasColumnOrder(3)
                              .HasColumnType("varchar");
     }
   }

As you can see in the above example, the Property() method is used to configure a property of an entity. The HasColumnName() method is used to change the column name of the Name property. Also, the HasColumnOrder() and HasColumnType() methods change the order and data type of the corresponding column.

Configure Null or Not Null Column

EF 6 API will create a Not Null column for a primitive data type property because primitive data type cannot be null unless it is marked as nullable using the "?" sign or Nullable<T> type. we Use IsOptional() method to make a column nullable. In the same way, we use IsRequired() method to make a column Not Null.


   public class OrganizationDbContext: DbContext 
   {

    public DbSet<Employee> Employees { get; set; }
        
      protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            //Configure Null Column
          modelBuilder.Entity<Employee>()
                               .Property(p => p.AadharNumber)
                               .IsOptional();
                        
            //Configure NotNull Column
            modelBuilder.Entity<Employee>()
                                  .Property(p => p.Name)
                                  .IsRequired();
    }
  }

Configure Column Size

By-Default Entity Framework generates each column of Max size. You can override this convention, as shown below.


   public class OrganizationDbContext: DbContext 
   {

    public DbSet<Employee> Employees { get; set; }
        
     protected override void OnModelCreating(DbModelBuilder modelBuilder)
     {
        //Set StudentName column size to 50
        modelBuilder.Entity<Employee>()
                              .Property(p => p.Name)
                              .HasMaxLength(50); // set column size to 50
                        
        
        modelBuilder.Entity<Employee>()
                             .Property(p => p.Name)
                             .HasMaxLength(50).IsFixedLength();// set column size to 50 and convert 
                                                                                      //     nvarchar to ncahr
                        
        
            modelBuilder.Entity<Product>()
                                  .Property(p => p.price)
                                  .HasPrecision(18, 2);  //Set size decimal(18,2)
      }
   }

As you can see in the above example, we used the HasMaxLength() method to set the size of a column. The IsFixedLength() method converts nvarchar to nchar type. In the same way, the HasPrecision() method has been used to change the precision of the decimal column.