Code First Entity Framework - Basic Fluent API

1. As we saw in the earlier article Code First Entity Framework - Data Annotations, you can mark up your data object using attributes to control how Entity Framework generates a database to match your data objects. Some people don't like using Data Annotations, and EF provides a programmatic alternative.
2. Like before we have our data object, and we'll use the same example as last time of a school, and you need a Pupil object. You design the POCO object in code with 4 properties, id, name, DOB, and primary school attended:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace TestEF.Entity
{
    public class Pupil
    {
        public int PupilId { get; set; }

        public string Name { get; set; }

        public DateTime DateOfBirth { get; set; }

        public string PrimarySchool { get; set; }
    }
}
3. This time, instead of annotating the elements with attributes, we can programmatically do it in the code behind, and in particular by overriding the OnModelCreating event of the DB context.
using System.Data;
using System.Data.Entity;
using System.Data.EntityModel;

namespace TestEF.Contexts
{
    public class SchoolContext : DbContext
    {
        public DbSet<TestEF.Entity.Pupil> Pupils { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            // we will put our Fluent code here
        }
    }
}
4. OK, as with last time where we used the [Key] attribute, we start with assigning which member is the Primary Key.
        modelBuilder.Entity<TestEF.Entity.Pupil>()
            .HasKey(fp => fp.PupilId);
This tells the modelBuilder that the Pupil entity (and the database to be created) has PupilId as its primary key. This is functionally identical to using the [Key] Data Annotation on the data object.
5. Last time we then added the [Required] annotation to the first three members that we wanted to be non-nullable in the database. This time we do it in code:
        modelBuilder.Entity<TestEF.Entity.Pupil>()
            .Property(fp => fp.PupilId)
            .IsRequired();

        modelBuilder.Entity<TestEF.Entity.Pupil>()
            .Property(fp => fp.Name)
            .IsRequired();

        modelBuilder.Entity<TestEF.Entity.Pupil>()
            .Property(fp => fp.DateOfBirth)
            .IsRequired();
This tells the modelBuilder that the for the PupilId, Name and DateOfBirth properties of the Pupil entity, they are required, and should be non nullable in the database.
6. In the same vein, we can add the annotations for StringLength and the Identity column to the elements, giving the completed OnModelCreating section:
using System.Data;
using System.Data.Entity;
using System.Data.EntityModel;
using System.ComponentModel.DataAnnotation;

namespace TestEF.Contexts
{
    public class SchoolContext : DbContext
    {
        public DbSet<TestEF.Entity.Pupil> Pupils { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<TestEF.Entity.Pupil>()
                .HasKey(fp => fp.PupilId);

            modelBuilder.Entity<TestEF.Entity.Pupil>()
                .Property(fp => fp.PupilId)
                .IsRequired();
                .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

            modelBuilder.Entity<TestEF.Entity.Pupil>()
                .Property(fp => fp.Name)
                .IsRequired()
                .HasMaxLength(200);

            modelBuilder.Entity<TestEF.Entity.Pupil>()
                .Property(fp => fp.DateOfBirth)
                .IsRequired();

            modelBuilder.Entity<TestEF.Entity.Pupil>()
                .Property(fp => fp.PrimarySchool)
                .HasMaxLength(200);
        }
    }
}
Note to use the DatabaseGeneratedOption enum we need to add a using line for System.ComponentModel.DataAnnotation (or use the fully qualified name in the code)
7. Now if we make sure we've added our model context data generation line to the Golbal.asax, and make sure we consume our SchoolContext from a webpage codebehind or MVC controller (see how we did this in the last article) then we will see that EF creates our database as specified by the Fluent API.
8. If you think that seems a little bloaty compared with the data Annotation version, you have to consider that the Fluent API can do things that would be more difficult with the Annotation version, such as:

Composite primary key
If we wanted id and name as the combined key, we can do that
    modelBuilder.Entity<TestEF.Entity.Pupil>()
        .HasKey(p => new { p.PupilId, p.Name });
Ignore a property
If the model contains elements we don't need to persist, we can tell EF
    modelBuilder.Entity<TestEF.Entity.Pupil>()
        .Ignore(p => p.PrimarySchool); 
Change column mapping
If we need the DB to have a different column name for the entity
    modelBuilder.Entity<TestEF.Entity.Pupil>()
        .Property(p => p.Name) 
        .HasColumnName("PupilName");
Change table mapping
If we need the DB table to have a different name
    modelBuilder.Entity<TestEF.Entity.Pupil>()
        .ToTable("Pupils_2011");
There are many more things you can do with the Fluent API, especially with regards to mappings between inherited classes and how they are stored in the database, but these are the basics.
And that's the basics of Entity Framework code-first using the Fluent API.