Database Initialization Strategies in Entity Framework Code-First

Database Initialization Strategies in Entity Framework Code-First

In this article, I am going to discuss Database Initialization Strategies in Entity Framework Code-First Approach with Examples. Please read our previous article where we discussed Database Initialization in Entity Framework Code First Approach with Examples.

Database Initialization Strategies in Entity Framework Code-First Approach

When we run the application code for the first time using Entity Framework Code-First Approach, then the database is created in the specified database server. But what happens when we run the application code from the second time onward? Will the Entity Framework create a new database every time we run the application? What about the Production Environment? How do you manage or alter the database schema when you change your domain classes? To handle these scenarios using Entity Framework Code-First Approach, we need to use one of the database initialization strategies.

There are four different database initialization strategies to use with Entity Framework Code First Approach. They are as follows:

CreateDatabaseIfNotExists:

This is the default initializer of Entity Framework Code First Approach. In this case, the Entity Framework API will create the database if the database does not exist as per the configuration, if the database exits it will use that existing database. However, in this database initialization strategy, if we update the model class properties, and if we add a new model class or delete any existing model class and re-run the application, then it will throw an exception.

Let us understand this with an example. Please modify the context class as follows. To use the CreateDatabaseIfNotExists Database initialization strategy, you need to do is, you have to set the CreateDatabaseIfNotExists database Initializer using the Database class within context class constructor which is shown in the below example.

using System.Data.Entity;
namespace EFCodeFirstDemo
{
    public class EFCodeFirstContext : DbContext
    {
        public EFCodeFirstContext() : base("name=MyConnectionString")
        {
            //Setting the Database Initializer as CreateDatabaseIfNotExists
            Database.SetInitializer(new CreateDatabaseIfNotExists<EFCodeFirstContext>());
        }
        
        public DbSet<Student> Students { get; set; }
        public DbSet<Standard> Standards { get; set; }
    }
}

Now, run the application code. Once you run the application code, if the database name that you specified in the connection string (in this case the connection string with the name MyConnectionString) in the app.config or web.config file is present in the database, then it will use that database else it will create a new database.

Let us modify the Student model class as follows. Here, we have removed one property and added another property.

using System;
namespace EFCodeFirstDemo
{
    //Updating an Existing Entity
    public class Student
    {
        public int StudentId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime? DateOfBirth { get; set; }
        public byte[] Photo { get; set; }
        public decimal Height { get; set; }
        //Commenting the following Property
        //public float Weight { get; set; }
        //Adding the following Property
        public string Branch { get; set; }
        public virtual Standard Standard { get; set; }
    }
}

Now, if you run the application code, then you will get one exception as shown in the below image.

CreateDatabaseIfNotExists

DropCreateDatabaseIfModelChanges:

In this case, the Entity Framework API will create the database if the database does not exist and if the database exits, then it will use that existing database for the first time. However, as the name suggests, it will drop an existing database and creates a new database, if your model classes (entity classes) have been changed. So, you do not have to worry about maintaining your database schema, when your model classes change.

As we have modified the Student Model class, let us modify the context class as follows to use DropCreateDatabaseIfModelChanges database Initializer.

using System.Data.Entity;
namespace EFCodeFirstDemo
{
    public class EFCodeFirstContext : DbContext
    {
        public EFCodeFirstContext() : base("name=MyConnectionString")
        {
            //Setting the Database Initializer as DropCreateDatabaseIfModelChanges
            Database.SetInitializer(new DropCreateDatabaseIfModelChanges<EFCodeFirstContext>());
        }
        
        public DbSet<Student> Students { get; set; }
        public DbSet<Standard> Standards { get; set; }
    }
}

Now, run the above code and this time, it will not give you any error. In this case, as the model is changed, so, first it will drop the database, and then it will create a new database with the updated model. But the point that you need to remember is, the previous data what you stored in the database is lost.

DropCreateDatabaseAlways:

As the name suggests, in this case, the Entity Framework API will always drop an existing database every time you run the application and created the database irrespective of whether your model classes have changed or not. This database initialization strategy will be useful when you want a fresh database every time you run the application, for example when you are developing the application. To use this database initializer, modify the context class as follows:

using System.Data.Entity;
namespace EFCodeFirstDemo
{
    public class EFCodeFirstContext : DbContext
    {
        public EFCodeFirstContext() : base("name=MyConnectionString")
        {
            //Setting the Database Initializer as DropCreateDatabaseIfModelChanges
            Database.SetInitializer(new DropCreateDatabaseAlways<EFCodeFirstContext>());
        }
        
        public DbSet<Student> Students { get; set; }
        public DbSet<Standard> Standards { get; set; }
    }
}

In this case, you will not get any exceptions as every time you run the application, it will drop the database and create a new database irrespective of whether the model is changed or not. If the database is in use, then you will get an exception.

Custom DB Initializer:

You can also create your own custom database initializer. If the above three approaches do not satisfy your requirements or you want to do some other process that initializes the database using the above initializer, then you need to go with Custom DB Initializer.

To create your own custom DB Initializer, you need to create a class by inheriting from any one database Initializer class and override the Seed method. In our coming article, we will discuss the need and use of the Seed method in detail. Let us create a class file with the name MyCustomDBInitializer and then copy and paste the following code into it.

using System.Data.Entity;
namespace EFCodeFirstDemo
{
    public class MyCustomDBInitializer : CreateDatabaseIfNotExists<EFCodeFirstContext>
    {
        protected override void Seed(EFCodeFirstContext context)
        {
            //Seed: A method that should be overridden to actually add data to the context for seeding.
            //The default implementation does nothing.
            base.Seed(context);
        }
    }
}

In the above example, the MyCustomDBInitializer is a custom database initializer class that is derived from CreateDatabaseIfNotExists. This separates the database initialization code from a context class. Now, let us use the above MyCustomDBInitializer in our context class. So, modify the context class as follows:

using System.Data.Entity;
namespace EFCodeFirstDemo
{
    public class EFCodeFirstContext : DbContext
    {
        public EFCodeFirstContext() : base("name=MyConnectionString")
        {
            //Setting the Database Initializer as MyCustomDBInitializer
            Database.SetInitializer(new MyCustomDBInitializer());
        }
        
        public DbSet<Student> Students { get; set; }
        public DbSet<Standard> Standards { get; set; }
    }
}

Note: Entity Framework Code-First Approach has different database initialization strategies like CreateDatabaseIfNotExists, DropCreateDatabaseIfModelChanges, and DropCreateDatabaseAlways. However, there are some problems with these strategies. For example, if you already have data (other than seed data) or existing Stored Procedures, triggers, etc (which are created at the database level). in your database. These strategies are used to drop the entire database and recreate it, so you would lose the data and other DB objects. In our coming article, we will discuss how to update the database schema when our model changes without losing any existing data or other database objects.

Set the Database Initializer in the Configuration File:

It is also possible to set the Database Initializer in the configuration file. For example, to set the database initializer as DropCreateDatabaseAlways, add the following in the app.config file:

<configuration>
    <appSettings>
    <add key="DatabaseInitializerForType EFCodeFirstDemo.EFCodeFirstContext, EFCodeFirstDemo"         
        value="System.Data.Entity.DropCreateDatabaseAlways`1[[EFCodeFirstDemo.EFCodeFirstContext, EFCodeFirstDemo]], EntityFramework" />
    </appSettings>
</configuration>

To Set the Custom Database Initializer in the Configuration File, add the following in the app.config file:

<configuration>
    <appSettings>    
    <add key="DatabaseInitializerForType EFCodeFirstDemo.EFCodeFirstContext, EFCodeFirstDemo"
         value="EFCodeFirstDemo.MyCustomDBInitializer, EFCodeFirstDemo" />
    </appSettings>
</configuration>
How to Turn off the DB Initializer?

You can also turn off the database initializer for your application. Suppose, you do not want to lose existing data in the production environment, then you can turn off the initializer. Please modify the Context class as follows to turn off the database initializer.

using System.Data.Entity;
namespace EFCodeFirstDemo
{
    public class EFCodeFirstContext : DbContext
    {
        public EFCodeFirstContext() : base("name=MyConnectionString")
        {
            //Disable Database Initializer
            Database.SetInitializer<EFCodeFirstContext>(null);
        }
        
        public DbSet<Student> Students { get; set; }
        public DbSet<Standard> Standards { get; set; }
    }
}

You can also turn off the database initializer in the configuration file as follows:

<configuration>
    <appSettings>    
    <add key="DatabaseInitializerForType EFCodeFirstDemo.EFCodeFirstContext, EFCodeFirstDemo"
         value="Disabled" />
    </appSettings>
</configuration>

In the next article, I am going to discuss How to Configure Domain Classes in Entity Framework Code-First with Examples. Here, in this article, I try to explain Database Initialization Strategies in Entity Framework Code-First Approach and I hope you enjoyed this Database Initialization Strategies in Entity Framework Code-First Approach article. Please give your valuable feedback and suggestions about this article.

Leave a Reply

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