Fluent API in Entity Framework Core

Fluent API in Entity Framework Core

In this article, I am going to discuss How to Implement Fluent API Configurations in Entity Framework Core (EF Core) with Examples. Please read our previous article, where we discussed ConcurrencyCheck Attribute in Entity Framework Core with Examples.

Fluent API in Entity Framework Core:

Like the Data Annotation Attribute, the Entity Framework Core provides Fluent API, which we can also use to configure the domain classes, which will override the default conventions which the Entity Framework Core follows.

The EF Core Fluent API is based on the Fluent API Design Pattern (also known as Fluent Interface Design Pattern), where Method Chaining formulates the result. So, before proceeding further and understanding the Fluent API in EF Core, we first need to understand the Fluent Interface Design Pattern and Method Chaining in C#.

What is the Fluent Interface Design Pattern?

The Fluent Interface Design Pattern is a software design pattern that is used to create a more readable and expressive API by allowing method chaining. It aims to make the code more intuitive and natural to read, often resembling sentences or phrases in human language.

In C#, a fluent interface is usually implemented by returning the instance of the object being manipulated from each method call, which allows subsequent methods to be chained together. This pattern is commonly used in libraries and APIs to provide a concise and fluid way of configuring or interacting with objects.

The main objective of the Fluent Interface Design Pattern is to apply multiple methods to an object by connecting them with dots (.) without having to re-specify the object name each time. Let us understand How to Implement a Fluent Interface Design Pattern with an example. Let us say we have the following Student class.

What is the Fluent Interface Design Pattern?

Now, if we want to consume the above Student class, we generally create an instance of the Student class, and then we need to set the respective properties of the Student class as shown in the image below.

What is the Fluent Interface Design Pattern?

The Fluent Interfaces Design Pattern simplifies our object consumption code by making our code more simple, readable, and understandable. Is it not nice to set the Student object properties as shown in the below image?

What is the Fluent Interface Design Pattern?

If we consume the object like the above interface, it is like speaking a sentence that would make the class consumption code more simple, readable, and understandable. Now, the next big thing that we need to understand is how to implement this. To implement this, we have something called Method Chaining.

What is Method Chaining?

Method chaining is nothing but a technique or process where each method sets the value of a property of an object and then returns an object, and all these methods can be chained together to form a single statement. In order to implement method chaining, first, we need to create a wrapper class around the Student class, as shown in the below image.

What is Method Chaining?

As you can see in the above FluentStudent class, here we have created methods for each Student property. First, we create an instance of Student Class, and then, in each method, we are setting the value of the respective Student Property. Further, notice that the return type of each method is set to the FluentStudent, which is important; because of this, we can call subsequent methods using the dot operator. Now the above fluent interface is going to be consumed by the client. So, with the above FluentStudent class in place, now the client code looks as shown below.

How to Implement Fluent API Configurations in Entity Framework Core (EF Core) with Examples

The Complete Example Code of Fluent Interface Design Pattern:

Whatever we have discussed so far is given in the below example. The following example shows how to implement Fluent Interface Design Pattern in C#.

using System;
namespace FluentInterfaceDesignPattern
{
    public class Program
    {
        static void Main(string[] args)
        {
            FluentStudent student = new FluentStudent();
            student.StudentRegedNumber("BQPPR123456")
                   .NameOfTheStudent("Pranaya Rout")
                   .BornOn("10/10/1992")
                   .StudyOn("CSE")
                   .StaysAt("BBSR, Odisha");

            Console.Read();
        }
    }

    public class Student
    {
        public string? RegdNo { get; set; }
        public string? Name { get; set; }
        public DateTime DOB { get; set; }
        public string? Branch { get; set; }
        public string? Address { get; set; }
    }

    public class FluentStudent
    {
        private Student student = new Student();
        public FluentStudent StudentRegedNumber(string RegdNo)
        {
            student.RegdNo = RegdNo;
            return this;
        }
        public FluentStudent NameOfTheStudent(string Name)
        {
            student.Name = Name;
            return this;
        }
        public FluentStudent BornOn(string DOB)
        {
            student.DOB = Convert.ToDateTime(DOB);
            return this;
        }
        public FluentStudent StudyOn(string Branch)
        {
            student.Branch = Branch;
            return this;
        }
        public FluentStudent StaysAt(string Address)
        {
            student.Address = Address;
            return this;
        }
    }
}
Advantages and Disadvantages of the Fluent Interface Design Pattern:
Advantages of the Fluent Interface Design Pattern:
  1. Readability: Method chaining provides a natural, readable flow, often resembling a sequence of statements or commands.
  2. Conciseness: Fluent syntax can make the code more concise and expressive.
  3. Discoverability: The fluent interface often guides users toward available options and actions.
  4. Intuitive: The syntax can be more intuitive, especially for configuring or building complex objects.
Disadvantages of the Fluent Interface Design Pattern:
  1. Learning Curve: While fluent interfaces can make code more expressive, they might have a learning curve for those unfamiliar with the pattern.
  2. Complexity: Overuse or excessive method chaining can lead to overly complex and difficult-to-debug code.
  3. Immutability: Fluent interfaces may not be suitable for cases where object immutability is crucial.

Now, I hope you understand the Fluent Interface Design Pattern. With this kept in mind, let us proceed and try to understand Fluent API in Entity Framework Core.

Configuring Fluent API in Entity Framework Core:

It would help if you remembered that Fluent API configuration can only be applied when Entity Framework Core builds the models from your domain classes. That means you can use Fluent API Only when you are working with EF Core Code First Approach.

In EF Core, the DbModelBuilder class acts as a Fluent API using which we can configure many different things. It provides more options for configurations than Data Annotation attributes.

In this case, we need to override the OnModelCreating method of DbContext class in our context class to inject the Fluent API configurations something like the below in Entity Framework Core. You can see we are calling many methods using the same modelBuilder object using the dot (.) operators, which is nothing but method chaining.

How to Implement Fluent API Configurations in Entity Framework Core (EF Core) with Examples

Note: You need to remember that in Entity Framework Core, you can configure a domain class using both Data Annotation Attributes and Fluent API simultaneously. In this case, EF Core will give precedence to Fluent API over Data Annotations Attributes.

Fluent API Configurations in Entity Framework Core:

In EF Core, the Fluent API configures the following things of a model class.

  1. Model-Wide Configuration: Configures an EF model to database mappings. Configures the default Schema, DB functions, additional data annotation attributes, and entities to be excluded from mapping.
  2. Entity Configuration: Configures entity to table and relationships mapping. For example PrimaryKey, AlternateKey, Index, table name, one-to-one, one-to-many, many-to-many relationships, etc.
  3. Property Configuration: Configures property to column mapping. For example, column name, default value, nullability, Foreignkey, data type, concurrency column, etc.

Now, let us proceed and try to understand the different methods available in each configuration.

Model-Wide Configurations in EF Core
  1. HasDbFunction(): Configures a database function when targeting a relational database.
  2. HasDefaultSchema(): Specifies the database schema.
  3. HasAnnotation(): Adds or updates data annotation attributes on the entity.
  4. HasSequence(): Configures a database sequence when targeting a relational database.
Entity Configurations in EF Core:
  1. HasAlternateKey(): Configures an alternate key in the EF model for the entity.
  2. HasIndex(): Configures an index of the specified properties.
  3. HasKey(): Configures the property or list of properties as Primary Key.
  4. HasMany(): Configures the Many parts of the relationship, where an entity contains the reference collection property of other types for one-to-many or many-to-many relationships.
  5. HasOne(): Configures the One part of the relationship, where an entity contains the reference property of other types for one-to-one or one-to-many relationships.
  6. Ignore(): Configures that the class or property should not be mapped to a table or column.
  7. OwnsOne(): Configures a relationship where this entity owns the target entity. The target entity key value is propagated from the entity it belongs to.
  8. ToTable(): Configures the database table that the entity maps to.
Property Configurations in Entity Framework:
  1. HasColumnName(): Configures the corresponding column name in the database for the property.
  2. HasColumnType(): Configures the data type of the corresponding column in the database for the property.
  3. HasComputedColumnSql(): Configures the property to map to computed columns in the database when targeting a relational database.
  4. HasDefaultValue(): Configures the default value for the column that the property maps to when targeting a relational database.
  5. HasDefaultValueSql(): Configures the default value expression for the column that the property maps to when targeting a relational database.
  6. HasField(): Specifies the backing field to be used with the property.
  7. HasMaxLength(): Configures the maximum length of data that can be stored in a property.
  8. IsConcurrencyToken(): Configures the property to be used as an optimistic concurrency token.
  9. IsRequired(): Configures whether the valid value of the property is required or whether null is a valid value.
  10. IsRowVersion(): Configures the property to be used in optimistic concurrency detection.
  11. IsUnicode(): Configures the string property, which can contain Unicode characters or not.
  12. ValueGeneratedNever(): Configures a property that cannot have a generated value when an entity is saved.
  13. ValueGeneratedOnAdd(): Configures that the property has a generated value when saving a new entity.
  14. ValueGeneratedOnAddOrUpdate(): Configures that the property has a generated value when saving a new or existing entity.
  15. ValueGeneratedOnUpdate(): Configures that a property has a generated value when saving an existing entity.

Note: In our next article, we will explain all the above Fluent API Configuration Methods with Examples using Entity Framework Core.

In the next article, I am going to discuss Relationships in Entity Framework Core using Fluent API with Examples. Here, in this article, I try to explain How to Configure Fluent API in Entity Framework Core with Examples. I hope you enjoyed this Fluent API configuration in the EF Core article.

Leave a Reply

Your email address will not be published. Required fields are marked *