Click here to Skip to main content
15,868,016 members
Articles / Web Development / ASP.NET

Fluent API vs Data Annotations- Working with Configuration-Part 1

Rate me:
Please Sign up or sign in to vote.
4.95/5 (19 votes)
15 Oct 2012CPOL4 min read 65.2K   17   28
Domain Model Layer will be better isolated from infrastructure implementation. 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”.


If you consider the DDD architecture designs, one thing you must fulfill that is isolation our Domain Model Layer. To achieve that, you must isolate Domain Entities from any other layers such as infrastructure layers, Data Persistence layers where you have a selected data technology. So you need to satisfy the  Persistence Ignorance Principle for domain Classes (Entities, Value-Objects, Domain Services, etc.). Here comes the question for right choice. This is the reason POCO entities are the right choice for DDD.

If you go further deep into Code First, you’ll see that the initial way to make the mappings from your POCO Domain Entities classes towards your final database tables is based on conventions. I have a question?? What will happen if those conventions are not ok (if you need to adjust to an existing database or whatever)?? So you need to customize those conventions. You can do that either in two ways. Let us start describing those two ways:

Code first leverages a programming pattern referred to as convention over configuration. Code first gives you two ways to add these configurations to your classes. One is using simple attributes called DataAnnotations within the ”System.ComponentModel.DataAnnotations“ namespace which is part of the .NET Framework and the other is using code first’s Fluent API, which provides you with a way to describe configurations imperatively, in code. Customizing it with Fluent API is a way that fits much better with the PI (Persistence Ignorant), because our Domain Model will be ignorant of those mappings which will be defined into our Data Persistence Infrastructure layer, so, our Domain Model Layer will be better isolated from infrastructure implementation. 

Everything that 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”. Learning the Fluent API is almost a must, the DataAnnotations are a nice-to-have for simple applications.

We will describe the example for MVC4 Code First application.

C#
public class Author
{
 public int AuthorId { get; set; }
 public string Name { get; set; }
 public string Description { get; set; }
 public byte[] Photo { get; set; }
 public virtual ICollection<Book> Books { get; set; }
}
C#
public class Book
{
 public int BookId { get; set; }
 public string Name { get; set; }
 public DateTime PublishDate { get; set; }
 public Author Author { get; set; }
}
C#
public class LibraryDB:DbContext
{
 public DbSet<Author> Authors { get; set; }
 public DbSet<Book> Books { get; set; }
}

The Author and Book class describes a particular Author that might have a collection of Books. So Author object can have one or more Books associated with it. Our class LibraryDB will inherit from DbContext in order to gain all of DbContext’s capabilities. Additionally, it will expose properties that return queryable sets, DbSets, of Author class and Book class. The last class represents a complete data layer that you can use in applications. For DbContext, you will be able to query, change, track and save Author and Book data. Thanks to DbContext :).

Let’s start with the Author class. There are three things I would like to change:

  1. Ensure the Name is provided.
  2. Limit the max length of Description field to 500 characters.
  3. Store the Photo into SQL Server image type.

We need “System.ComponentModel.DataAnnotations” assembly that is part of .NET 4.0. Apply the following code:

C#
public class Author
{
 public int AuthorId { get; set; }
 [Required]
 public string Name { get; set; }
 [MaxLength(500)]
 public string Description { get; set; }
 [Column(TypeName="image")]
 public byte[] Photo { get; set; }
 public virtual ICollection<Book> Books { get; set; }
}
C#
public class Book
{
 public int BookId { get; set; }
 [Required]
 public string Name { get; set; }
 public DateTime PublishDate { get; set; }
 public Author Author { get; set; }
}

The Required annotation needs no additional information, whereas the MaxLength and Column have parameter information that you need to provide. The parameter provided to the Column annotation is specific to the database that you are mapping to. We want to store Photo in a SQL Server image field. So we configured the data type. All three annotations will impact the databse schema. On the Book class, we have only placed the required annotation no character limit, so in the database schema you will find the length is nvarchar(max). Note that we can also use MinLength which is an interesting annotation. While MaxLength has a database counterpart, MinLength does not. MinLength will be used for EF validation without impacting the database.

MinLength is the only configuration that can be achieved using Data Annotation but has no counterpart in the Fluent API configurations.

If you opened up the database table, you will find the changes that we have made in our classes. We will discuss on EF DataBase Migration later.

Configuring with Fluent API

The concern of a Fluent API isn’t specific to Code First or the EF. The basic is chained method calls to produce code that is easy for the developers to read. The return type of each call then defines the valid methods for the next call. There are more reasons why developers like Fluent API.

C#
public class LibraryDB:DbContext
{
 public DbSet<Author> Authors { get; set; }
 public DbSet<Book> Books { get; set; }
 protected override void OnModelCreating(DbModelBuilder modelBuilder)
 {
   modelBuilder.Entity<Author>()
    .Property(n => n.Name).IsRequired();
   modelBuilder.Entity<Author>()
    .Property(d => d.Description).HasMaxLength(500);
   modelBuilder.Entity<Author>()
    .Property(p => p.Photo).HasColumnType("image");
   modelBuilder.Entity<Book>()
    .Property(n => n.Name).IsRequired();
 }
}

Let us describe the mechanism above code, how it works actually. Julia Lerman & Rowan Miller describes nicely in their “Programming Entity Framework Code First” book. “When it's time to build the model, the DBContext first looks at the classes and learns what it can from them. At this point, the context is ready to reason out the model, but there is an opportunity for the developers to interrupt the context and perform additional configuration. DbContext.OnModelCreating method is called by the context just before the model is built. The method is virtual, so you can override it and insert your own logic. This is where the Fluent API configuration goes”.

Stay Tuned: Be Right Back with more advanced…


License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Singapore Singapore
A life-long-learner, maker and soft music fan. Likes building things to solve problems. Years of successful records serving mid and large scale .NET applications in domestic and international client environment. Expertise in different areas of software development life cycles and Software Architecture.

Always looks for new technology and loves to get hands dirty Smile | :)

Comments and Discussions

 
GeneralMy vote of 4 Pin
Paolo Botti22-Jan-15 0:26
professionalPaolo Botti22-Jan-15 0:26 
GeneralMy vote of 5 Pin
dgDavidGreene18-Jan-13 19:21
dgDavidGreene18-Jan-13 19:21 
GeneralRe: My vote of 5 Pin
Monjurul Habib7-Mar-13 6:41
professionalMonjurul Habib7-Mar-13 6:41 
GeneralMy vote of 5 Pin
Mahbub_Hasan_Aiub20-Nov-12 6:49
Mahbub_Hasan_Aiub20-Nov-12 6:49 
GeneralRe: My vote of 5 Pin
Monjurul Habib20-Nov-12 6:52
professionalMonjurul Habib20-Nov-12 6:52 
GeneralMy vote of 5 Pin
hopeful4ever19-Oct-12 8:30
hopeful4ever19-Oct-12 8:30 
GeneralRe: My vote of 5 Pin
Monjurul Habib19-Oct-12 9:11
professionalMonjurul Habib19-Oct-12 9:11 
GeneralMy vote of 5 Pin
fjdiewornncalwe16-Oct-12 4:41
professionalfjdiewornncalwe16-Oct-12 4:41 
GeneralRe: My vote of 5 Pin
Monjurul Habib16-Oct-12 5:40
professionalMonjurul Habib16-Oct-12 5:40 
GeneralMy vote of 5 Pin
cisjackie15-Oct-12 18:03
cisjackie15-Oct-12 18:03 
GeneralRe: My vote of 5 Pin
Monjurul Habib15-Oct-12 18:10
professionalMonjurul Habib15-Oct-12 18:10 
GeneralMy vote of 5 Pin
Hasibul Haque15-Oct-12 17:26
professionalHasibul Haque15-Oct-12 17:26 
GeneralRe: My vote of 5 Pin
Monjurul Habib15-Oct-12 18:09
professionalMonjurul Habib15-Oct-12 18:09 
GeneralMy 5 Pin
Shahriar Iqbal Chowdhury/Galib15-Oct-12 10:54
professionalShahriar Iqbal Chowdhury/Galib15-Oct-12 10:54 
GeneralRe: My 5 Pin
Monjurul Habib15-Oct-12 10:55
professionalMonjurul Habib15-Oct-12 10:55 
GeneralMy vote of 5 Pin
Sk. Tajbir15-Oct-12 10:16
Sk. Tajbir15-Oct-12 10:16 
GeneralRe: My vote of 5 Pin
Monjurul Habib15-Oct-12 10:20
professionalMonjurul Habib15-Oct-12 10:20 
GeneralMy vote of 5 Pin
MostofaHaider15-Oct-12 8:47
MostofaHaider15-Oct-12 8:47 
GeneralRe: My vote of 5 Pin
Monjurul Habib15-Oct-12 8:48
professionalMonjurul Habib15-Oct-12 8:48 
GeneralRe: My vote of 5 Pin
fjdiewornncalwe15-Oct-12 10:09
professionalfjdiewornncalwe15-Oct-12 10:09 
GeneralRe: My vote of 5 Pin
Monjurul Habib15-Oct-12 10:11
professionalMonjurul Habib15-Oct-12 10:11 
GeneralRe: My vote of 5 Pin
Monjurul Habib15-Oct-12 10:19
professionalMonjurul Habib15-Oct-12 10:19 
GeneralRe: My vote of 5 Pin
fjdiewornncalwe15-Oct-12 10:37
professionalfjdiewornncalwe15-Oct-12 10:37 
GeneralRe: My vote of 5 Pin
Monjurul Habib15-Oct-12 10:45
professionalMonjurul Habib15-Oct-12 10:45 
GeneralRe: My vote of 5 Pin
fjdiewornncalwe15-Oct-12 10:49
professionalfjdiewornncalwe15-Oct-12 10:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.