Shadman Kudchikar

Entity Framework Enum Code First

Entity Framework Enum Code First

Contents

Introduction

Enum or Enumerations is used to declare a list of named integer constants. The enum is used to give a name to each constant so that the constant integer can be referred using its name.

Enumerations appear in your source code. These are things that affect program logic because you’re going to have conditional statements based on the state of some entity comparing it with some enum value. This enums represents numerical values which can get used in place of IDs in database tables.

Creating Enum

C# usually manages the IDs of enumeration for you.

As you version your code from one version to the next you want to make sure that those IDs remain consistent. To keep it consistent we assing values to each enum. Below is the code for StatusEnum we will be working on.

public enum StatusEnum
{
    FullTime = 0,
    PartTime = 1,
    Casual = 2,
    Contract = 3
}

Creating Lookup Table Class Using Code-First Approch

We will create another class named Status to represent our above enum as lookup table. Status class will act as a lookup table for our above StatusEnum. Here we use StatusEnum as datatype for our IDs to constrain the Status ID to just those values in the StatusEnum.

public class Status
{
    public StatusEnum Id { get; set; }
    public string Name { get; set; }
}

Define Foreign Key Constraint Using Code-First Conventions

Below is the Employee class that represent our Employee Table. Below code will create the Foreign Key relationship inside a Employee, and constrain the Status ID to just those values in the StatusEnum.

public class Employee
{
    public long Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    //Below code will create the Foreign Key relationship inside a Employee, and 
    //constrain the Status ID to just those values in the StatusEnum
    //Here StatusEnum will act as ID/Primary key for Status table and will be seeded manually 
    //Look context class for additional model builder configuration which disables the identity for Status table and
    //Also look seed method in configuration.cs file
    public StatusEnum StatusId { get; set; }
    public virtual Status Status { get; set; }
    

}

Disable Identity for Lookup Table IDs

When you’re backing enum with the database you want to control those IDs. We can disable the identity on our lookup Status table by confuguring the modelBuilder. By disabling the identity we will have control over the IDs we want to poplulate, which will be the enum values in our case.

public class ApplicationContext:DbContext
{
    public DbSet<Employee> Employees { get; set; }
    public DbSet<Status> Statuses { get; set; }

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

        modelBuilder.Entity<Status>()
            .Property(s => s.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
    }
}

Seeding Enum into Lookup Table

In order to insert the enumeration values into the database we’re going to take advantage of the seed method. This is a method on the configuration class that was created whenever we enabled migrations for the first time. Let’s jump to the code, and see how we can create seed data for an enumeration.

internal sealed class Configuration : DbMigrationsConfiguration<MigrationTutorial.Models.ApplicationContext>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
    }

    protected override void Seed(MigrationTutorial.Models.ApplicationContext context)
    {
        //  This method will be called after migrating to the latest version.

        //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
        //  to avoid creating duplicate seed data.

        context.Statuses.AddOrUpdate( 
            x=> x.Id,
            Enum.GetValues(typeof(StatusEnum))
                .OfType<StatusEnum>()
                .Select(x => new Status() { Id = x, Name=x.ToString() })
                .ToArray());
    }
}

By using the above method for seeding we can eliminate mistakes and error occur in populating enums in our lookup table.

References

Entity Framework Migrations For Teams

Entity Framework Migrations For Teams

Contents

Why Use Database Migrations

Teams usually use version control systems to manage and collaborate on changes made to versions of source code. Different developers can develop on divergent, relatively older or newer branches of the same source code to make changes and additions during development.

Supposing that the software under development interacts with a database, every version of the source code can be associated with at least one database schema with which it is compatible.

Schema migration tools can be said to solve versioning problems for database schemas just as version control systems solve versioning problems for source code.

In practice, many schema migration tools actually rely on a textual representation of schema changes (such as files containing SQL statements) such that the version history of schema changes can effectively be stored alongside program source code within VCS. Its Entity Framework Migrations in our case which gets stored in migration folder in our project.

This approach ensures that the information necessary to recover a compatible database schema for a particular code branch is recoverable from the source tree itself. Another benefit of this approach is the handling of concurrent conflicting schema changes; developers may simply use their usual text-based conflict resolution tools to reconcile differences.

Crafting Migrations in EF

1. Enable migration

Enable migration with Enable-Migrations command. This will be one time process and done only once in your project lifetime.

2. Update Entities and Add Migration

After creating or making changes in Entites and Mapping Configuration you will add migration to migration folder using Add-Migration command followed by mirgration name.

3. Spot Checking

Spot checking migration is the important step before updating database which people usually forget or ignore. While spot checking, you should look code generated for default parameters of datatype and relationships between entities in mirgration file. If you are happy with generated migrations you can move to updating database step or delete the migration file and update the enitiy and mapping configuration as per your need.

Also note dont update the code in mirgration file directly as that will be a bad idea because its nothing but just reflection of the entity models and mapping configuration and that will not change your models.

4. Update-Database

If everthing is as per requirement in your mirgration run the Update-Database command.

Also note that steps 2 to 4 are repetative steps for any change you do in model but enable migration is just one time process.

Merge Workflow With Migrations

Issues start to arise when you have multiple developers making changes to the EF model and submitting to source control at the same time. What EF lacks is a first class way to merge your local migrations with migrations that another developer has submitted to source control since you last synced.

So in such cases while running Update-Database command can raise a warning:

Unable to update database to match the current model because there are pending changes and automatic migration is disabled. Either write the pending model changes to a code-based migration or enable automatic migration

This issue arise when two or more migrations has same base migration, or you can say that, this happens when two or more migrations are created from same source control base branch and then merged together.

You can create custom merge migration, which has updated resx and model but not any up and down steps, to solve this issue.

The command to create this custom merge migration is Add-Migration -IgnoreChanges followed by migration name.

Here rexs files are nothing but binary snapshot of current model attached to migration, which is used to find the required database changes in subsequent migrations, thus by updating it in custom merge branch you solve the model difference issue.

For addition information refer this article

Handling Special Cases With Migrations

Best Practices

References