Fluent API in Entity Framework Core

Fluent API in Entity Framework Core

In this article, I will discuss How to Implement Fluent API Configurations in Entity Framework Core (EF Core) with Examples. Please read our previous article discussing 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 that the Entity Framework Core follows.

Fluent API in Entity Framework Core (EF Core) provides a way to configure the model classes and relationships between them using C# code rather than attributes. This allows for a more detailed level of configuration that might not be possible using only Data Annotation Attributes. The Fluent API configurations typically reside in the OnModelCreating method of our DbContext subclass.

The EF Core Fluent API is based on the Fluent API Design Pattern (AKA 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 creates 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?

Consuming the object like the above interface is like speaking a sentence that would make the class consumption code more simple, readable, and understandable. The next big thing we must 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. To implement method chaining, first, we must create a wrapper class around the Student class, as shown in the image below.

Fluent API Configurations in Entity Framework Core with Examples

As you can see in the above FluentStudent class, we have created methods for each Student property. First, we create an instance of Student Class, and then, in each method, we set 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, 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 a 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:

The point that you need to remember is 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 the DbContext class in our context class to inject the Fluent API configurations, something like the one below in Entity Framework Core. We call 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: The point that you need to remember is 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(): The HasOne() method specifies the navigation property representing the relationship’s principal end.
  6. WithOne(): The WithOne() method specifies the navigation property on the dependent end.
  7. HasForeignKey<TDependent>(): The HasForeignKey<TDependent>() method is used to specify which property in the dependent entity represents the foreign key.
  8. HasMany(): Configures a relationship where this entity type has a collection that contains instances of the other type in the relationship. That means it specifies the ‘many’ side of the relationship. 
  9. Ignore(): Configures that the class or property should not be mapped to a table or column.
  10. 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 when targeting a relational database.
  4. HasDefaultValue(): Configures the default value for the column the property maps to when targeting a relational database.
  5. HasDefaultValueSql(): Configures the default value expression for the column the property maps to when targeting a relational database.
  6. HasField(): Specifies the backing field for the property.
  7. HasMaxLength(): Configures the maximum data length 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 for 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 upcoming article, I will explain all the above Fluent API Configuration Methods with Examples using Entity Framework Core.

Advantages and Disadvantages of Fluent API Configurations in Entity Framework Core:

Fluent API configurations in Entity Framework Core provide a programmatic way to configure your model to database mappings. Let us see the advantages and disadvantages of Fluent API Configurations in Entity Framework Core.

Advantages of Fluent API Configurations in Entity Framework Core:
  • Granular Configuration: Fluent API provides a detailed configuration level, which is impossible with Data Annotations alone.
  • Separation of Concerns: By keeping configuration separate from the domain classes, our entity classes can remain POCOs (Plain Old CLR Objects) without any EF-specific attributes, making them cleaner.
  • Unified Configuration Location: Configurations are centralized in one place (typically in the OnModelCreating method), which makes it easier to get an overview of all configurations and relationships between entities.
  • Advanced Mappings: Fluent API provides more options for configuring complex relationships, inheritance mapping strategies, and other advanced features.
  • No External Dependencies: Since Fluent API doesn’t require attributes, there’s no need to reference EF assemblies in domain projects if they are separated.
  • Dynamic Configurations: Programmatic configurations can be dynamic based on conditions, whereas Data Annotations are static.
Disadvantages of Fluent API Configurations in Entity Framework Core:
  • Learning Curve: Fluent API might have a steeper learning curve than straightforward Data Annotations for newcomers.
  • Verbosity: Fluent API can be more verbose. For simple configurations, Data Annotations can be more concise.
  • Separation from Entity: Since the configuration is separate from the entity class, developers might need to jump back and forth between the entity class and configuration to understand or modify the mapping.
  • Discoverability: For new developers or developers unfamiliar with Fluent API, it might be less discoverable compared to seeing attributes directly on properties in an entity class.
  • Potential for Mistakes: Due to the detailed nature of Fluent API, there’s a higher chance of making mistakes, especially when configuring complex relationships.
  • Maintenance: As your application grows, the OnModelCreating method can become large and unwieldy, making maintenance challenging.

In Real-Time Applications, many teams find a balance by combining Fluent API and Data Annotations. Simple configurations might be handled with annotations for clarity and brevity. In contrast, Fluent API can do more complex configurations or those that need to be separated from the entity class. The choice ultimately depends on the specific needs of the project and the team’s preferences.

In the next article, I will 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 *