Entity Framework Code First Approach to Auto Migrate table

+1 vote
asked Jul 16, 2013 in Entity Framework by anonymous

What is code first approach in .NET? How can we use code first approach with entity framework and create tables and relationship of tables in database automatically from .NET application? How can I use Nuget Packages to do that?

Share

2 Answers

+1 vote
answered Jul 18, 2013 by Aadhira (1,213 points)
selected Jul 18, 2013 by administrator
 
Best answer

Entity Framework Code First Approach:

Before we had the ability to right code first approach, if we want to work with entity framework to connect to database and work with tables, then first we need to create tables in database, then create .edmx file. without that tables created first, we cannot write any code which needs to connect to database. When we have .edmx file, the automatic code generator will create some automatic code whenever we add or remove tables and views that we want to talk to. That automatic code was having the designer information to display the table is in the designer, also it created mapping file between the clr objects and the database table object. Then only we can write the code to work with the database. That approach is called Database first approach. That means we will design the database first and then do the code.

Then, there was an another approach called model first approach where we will create the .edmx model first and use that model to create the database.

But in both the above cases, we need to .edmx files and also, we need to have tables available to do any development further.

But in code first approach, we will be able to the development with regular clr objects which are called POCO. i.e Plain Old Clr Objects. Using this approach, we can create our clr objects without need to worry how are we going to connect to db in the beginning itself. Of course we need to write some code to connect to DB, but you are no longer need to use any specific type object from which you need to derive your domain object. Because in the earlier approaches, we usually have domain objects and its properties mapped with the object and properties generated by the code generator. So, it was making complexity to do any simple unit testing.

Let see step by step guide for how to write a simple application using entity framework code first approach. Let say, we have a screen with First Name, Last Name and Address. The values are fetch from database table customer. With code first approach, we start development from the UI.

We create a view with with those 3 fields and the screen shot is below.
ui screen shot ef code first

Next, domain objects EmployeeDetail and Address are created. Each employee will have an address. So, both are having parent child relationship. Just to support WPF data binding using MVVM design pattern, I am using INotifyPropertyChanged interface on the domain object.

To inform the entity framework about the relationship between the EmployeeDetail table and Address table, we have used DataAnnotation methodology and provided PrimaryKey and ForeignKey. When we mention the ForeignKey annotation, we also need to pass the property name of the Parent table. Please not that it is not the Parent table class name (in out example it is "EmployeeDetail"). We need to pass the property which is on the type of EmployeeDetail. i.e "Employee" property in our example. If both the property name and the property type are same, then no issue. Otherwise, you will get exception.

Primary key can be automatically identified the entity framework if you have any property with the following naming convention.

Property name is "Id"
Or
Property name is Name of the class + "Id". In our example it would be EmployeeDetailId.

If you do not follow the naming format, then you need specify the Key annotation explicitly. If you do not use the Annotation method, you may need to use the Fluent API method to specify the relationship.

public class EmployeeDetail : INotifyPropertyChanged
{
    private int employeeId;
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int EmployeeId
    {
        get { return employeeId;}
        set
        {
            employeeId = value;
            OnPropertyChanged("EmployeeId");
        }
    }

    private string firstName;
    public string FirstName
    {
        get{ return firstName; }
        set
        {
            firstName = value;
            OnPropertyChanged("FirstName");
        }
    }

    private string lastName;
    public string LastName
    {
        get{ return lastName; }
        set
        {
            lastName = value;
            OnPropertyChanged("LastName");
        }
    }

    //Marked as virtual to support lazy loading
    public virtual Address Address { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
public class Address : INotifyPropertyChanged
{
    private int _buildingNumber;
    public int BuildingNumber
    {
        get{ return _buildingNumber; }
        set
        {
            _buildingNumber = value;
        }
    }

    private string _street;
    public string Street
    {
        get{ return _street; }
        set
        {
            _street = value;
            OnPropertyChanged("Street");
        }
    }

    private int employeeId;
    [Key, ForeignKey("Employee")] //Make sure to give Property Name of the EmployeeDetail in this class. Not the datatype name (Not EmployeeDetail)
    public int EmployeeId
    {
        get{ return employeeId; }
        set
        {
            employeeId = value;
            OnPropertyChanged("EmployeeId");
        }
    }

    public virtual EmployeeDetail Employee { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

Now we can add reference to Entity Framework. To do that, right click on the project on which you need to add reference and select "Manage NuGet Packages" from the context menu. It will open the below window where search for the Entity Framework and make sure you have selected the "Stable Only" option. Otherwise, you might see pre released entity framework. Once you find the stable version, click on the install button.

context menu to open nuget window

nuget install entity framework stable2

Once you install entity framework using NuGet packages, it will install all required entity framework dlls and its dependencies to the project. Now you will be seeing on new config file called "packages.config" which is related to NuGet packages where it maintains the installed packages. Also, it would have created a new folder called "packages" in the physical folder path of the current solution. That will have all the dlls installed by the NuGet packages.

<packages>
  <package id="EntityFramework" version="5.0.0" targetFramework="net40-Client" />
</packages>

Next step, we need to have Context class. It is a simple class that has been derived from DbContext object which exist in "System.Data.Entity".
In this class, we need to create properties of type DbSet, where T is the domain model object type for which we want to create table. You can see that in the below code.

public class EmployeeContext : DbContext
    {
        public DbSet<EmployeeDetail> EmployeeDetail { get; set; }
    }

Without having Context class, automatic migration command of nuget packages will not work. So, first we need to have the context object created.

Article continued in the next answer

+1 vote
answered Jul 18, 2013 by Aadhira (1,213 points)

Continuation

Now, go to Tools -> Library Package Manager -> Package Manager Console
Then select the project on which you have the context class then type the following command on the console window.

nuget package manager console menu

enable migrations nuget command

enable-migrations -EnableAutomaticMigration

This command will enable the automatic migration used to create table in the database using the domain model and DbContext.

Now you should see new folder called "Migrations" which has a configuration file. Usually, this will be a internal class, but you can change to public if you want to access from different assembly. In the constructor of this class, you would see the "AutomaticMigrationsEnabled = true;". This is what enabling the automatic migrations.

public sealed class Configuration : DbMigrationsConfiguration<EFCodeFirstApproach.EmployeeContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = true;
        }

        protected override void Seed(EFCodeFirstApproach.EmployeeContext context)
        {
            context.EmployeeDetail.AddOrUpdate(
             p => p.EmployeeId,
             new EmployeeDetail
             {
                 EmployeeId = 1001,
                 FirstName = "FName",
                 LastName = "LName",
                 Address = new Address { BuildingNumber = 123, Street = "Main Street" }
             }
           );
        }
    }

I will explain the about the seed method, later on this article.

Now we need to write the code to initiate the Database Migration. This can be done using the below line of code. Add this code at the very beginning of the application run. For console application, it would be in Main method, for Winforms it would be in Program.cs and for WPF it would be in App.xaml.cs

Database.SetInitializer<EmployeeContext>(new MigrateDatabaseToLatestVersion<EmployeeContext, Configuration>("EmployeeContext"));

Once you run this, it will initiate the Configuration class to get the configuration detail and uses the EmployeeContext class which is derived from DbContext and uses the sql connection information configured in app.config as "EmployeeContext" and be ready to create tables.

The tables not created yet. It will not be created until we call the "EmployeeContext" object for the first time. Once you try to access any data from context object, that time only it will create the tables in DB.

I have written below code in viewmodel class to get the first employee. Once the code execution hit this line for the first time, it will create the table.

private void LoadEmployee()
{
  using (EmployeeContext context = new EmployeeContext())
  {
    EmployeeDetail = context.EmployeeDetail.Include("Address").FirstOrDefault();
  }
}

You may want to comment the Database.SetInitializer code for the second run of your application, otherwise it will try to recreate the tables again.

Now, we should see EmployeeDetail and Address table in the DB. EmployeeDetails table's primary key is being used as a foreign key of Address table.

Finally, the seed method.
Seed method is from Configuration class and it will be called very first time we query the context object after we call Database.SetInitializer. The purpose this method is to insert some dummy data into the newly created table which could be used for testing purpose. In our example, I have inserted one employee record with one address.

Below is the table created by entity framework automatic migrations

automatically created tables using entity framework

Your answer

Preview

Your name to display (optional):
Privacy: Your email address will only be used for sending these notifications.
Anti-spam verification:
To avoid this verification in future, please log in or register.
site design / logo / content © 2013 - 2015 pinfaq.com
...