Click here to Skip to main content
12,626,517 members (35,958 online)
Click here to Skip to main content
Add your own
alternative version

Stats

7.9K views
13 bookmarked
Posted

Manage Entity Framework code first in real time projects

, 29 Jul 2014 CPOL
Rate this:
Please Sign up or sign in to vote.

Introduction

Entity framework is really a great framework to work with. And the code first approach is becoming popular day by day. But if we don’t use entity framework code first in proper way it may turn into a devastating scenario. So in this article I will try to illustrate, what type of problems I have faced working with entity framework and how can we use this framework in a sure way.

Background

Before starting I am ambushing that, we have few knowledge about entity framework code first. At least we know how to create tables, relations and using seed data’s in entity framework.

If we don’t know, it wouldn’t be that hard to start with,

http://msdn.microsoft.com/en-us/data/jj193542.aspx

http://www.codeproject.com/Articles/796540/Relationship-in-Entity-Framework-Using-Code-First

http://www.codeproject.com/Articles/396822/Basic-Handling-and-Tips-of-Database-Relationships

Or just Google for some time, it would be just fine.

So, what entity framework code first needs?

  1. Models: to turn them into tables …
  2. Configurations for models: to create relations between tables, and formatting table columns structures …
  3. Context: to represent the database, connections, calling model configurations, database initializations, database load configurations …
  4. Initializers: to initialize database context, using seeds …
  5. Migrations: if model changes how to deal with old data’s or structures ...

What are the problem, you are been taking about?

The problems start when we are misusing sections like,

  1. Initialization of database context
  2. Working with migrations.

Let’s explain those sections.

1. Initialization of database context

To initialize Database context, we can use IDatabaseInitializers classes like

CreateDatabaseIfNotExists – creates database first, if there is no database available for the application, specified by the context and connection string. (Good for live projects)

But my host provider is not letting me to do such thing. He asks me to create database manually then use. What should I do now?

Updated requirement force you to add a new field to a table. So you did and provided the updated context. Now if we run the application, exception would be thrown pointing current context and existing database doesn’t Mach with one another. What should I do now?

DropCreateDatabaseIfModelChanges – drops the old database if it doesn’t match with the updated context, and creates new database as the context is pointing. (Good for development)

Updated requirement force you to add a new field to a table. So you did and provided the updated context. Now if we run the application, then old database would be dropped. All data would be loosed. What should I do now?

DropCreateDatabaseAlways - drops the old database and create a new one every time, whenever the context is initialized. (Good for testing, if database is small in size.)

We will not be able to store enough data to work with. No way should we use it, if the application is one real-time action. What should I do now?

 

So some says, why not use CreateDatabaseIfNotExists for live projects, DropCreateDatabaseIfModelChanges during development, and sql script to create database for first time. When we go live, replace DropCreateDatabaseIfModelChanges with CreateDatabaseIfNotExists, problem is solved. What about if one day we provide the update but forget to do such?

2. Working with migrations.

Migration is really a good way to work with entity frame work code first. It enables the database to hold information’s like, how many migrations are been made and when. Plus in migration files we can find out what changes where been made. Even we do go back and front between migrations. In next post we will talk about it.

But the problem is, it is little bit tricky to configure. If you have less time to do research, migration may force you to omit the option to use entity frame work code first. Because some time day by day applications expands so much, which enforce us to do change in the database data’s and tables relations etc.

And people don’t to take risks for big projects. They want to handle things as he used to do with Sql scripts.

What is the solution?

Here is the clue, Entity Framework can also be used to map context to existing database. So what we are going to do.

  1. Use a builder context for database, which use DropCreateDatabaseIfModelChanges. The context’s access in limited to a particular project only, not to other projects of the solution. Or can be inherited by other projects codes (using internal/ protected internal as access modifier). This will be used to rebuild the database.
  2. Use a mapper context for database, which is only mapped to database entities. This will be mainly used by application to effect tables.
  3. Inheriting common contents from Base context, for field table and configuration files

Mapper context

Mapper context is simple as like, which inherits base Context class.

We will use this context for any CRUD operations.

/*Context is only mapped to bd objects*/
public class UmsContext : Context
{
    public UmsContext() : base("DbUms")    //connection string name to base          
    {
        /*Configuration for the context*/
        Configuration.ProxyCreationEnabled = false;
        Configuration.LazyLoadingEnabled = false;
    }
}

Builder context

Builder context which also inherits from base Context class and its initializer class is like,

We will this context class only to recreate the database

/*Context drops the old database and creates new one*/
internal class UmsBuildContext : Context
{
    static UmsBuildContext()
    {
        //check connection string
        string connectionString = ConfigurationManager.ConnectionStrings["DbUms"].ConnectionString;
        Database.SetInitializer(new UmsBuildContextInitializer());
    }

    public UmsBuildContext()
        : base("DbUms") //connection string name to base
    {
    }
}

initializer may also have seeds like this

internal class UmsBuildContextInitializer
    : DropCreateDatabaseIfModelChanges<UmsBuildContext>
{
    protected override void Seed(UmsBuildContext context)
    {
        /*department seeds*/
        List<Department> departments = new List<Department>()
        {
            new Department(){Name = "Math"},
            new Department(){Name = "Physics"},
            new Department(){Name = "Chemistry"},              
        };
        context.Departments.AddRange(departments);
        context.SaveChanges();

        /*students seeds*/
        List<Student> students = new List<Student>()
        {
            new Student(){ Name = "Nitol", DepartmentId = 1},
            new Student(){ Name = "Tasnim", DepartmentId = 2},
            new Student(){ Name = "Ripon", DepartmentId = 3}
        };
        context.Students.AddRange(students);
        context.SaveChanges();
    }
}

As we said we want to set limit to the builder context. That’s why we are using internal as access modifier for UmsBuildContext. But it is also required to use this context for test projects to recreate the database for tests/ intentionally. So to access some of its functionally we are using this class inside a public class like

public class DbBuilder
{
    public void Build()
    {
        var departments = new UmsBuildContext().Departments.ToList();
    }
}

Base Context

The main base context is mainly holding all the table configurations and database entity references. And above contexts are inheriting it.

public class Context : DbContext
{
    /*all tbls*/
    public DbSet<Department> Departments { get; set; }
    public DbSet<Student> Students { get; set; }

    /*connection string provided by the sub class*/
    protected Context(string connectionString)
        : base(nameOrConnectionString: connectionString)
    {
    }

    /*get tbl by tbl type*/
    public DbSet<TSource> Table<TSource>() where TSource : class
    {
        return Set<TSource>();
    }

    /*all tbls configurations*/
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new DepartmentConfiguration());
        modelBuilder.Configurations.Add(new StudentConfiguration());
    }
}

Using the code

So if any change made to database structure, and want to rebuild the hold database we only have to call

/*Rebuild the db*/
//use only when we want to rebuild the database with seed data during production.
//avoid any use when the product is already been delivered to client.(best use in test code)
new DbBuilder().Build();

now let’s test the mapper context

/*see the datas*/
var db = new UmsContext();
var departments = db.Departments.ToList();
var departments2 = db.Table<Department>().ToList();

/*add new student with new department*/
var student = new Student()
{
    Name = "Rintu",
    Department = new Department() {Name = "CSE"}
};
db.Students.Add(student);
db.SaveChanges();

Here a new student and its department row would be created at the database. Means the mapper is working fine.

Change structure of the database

To do so we just have to do,

  1. Modify the model class.
  2. Rebuild the database at local machine.
  3. Compare recreated database with old one, to find the required alter/ update SQL-quires to update old database to current version. And use such quires to the old database.
  4. Replace old DLL with newly created one.

Limitations

  1. Yes there could be some errors which I haven't faced yet, or could make some ethical disturbance. So if you find any just let me know.
  2. I am not discouraging any one to use migrations. If you have time just do some RNDs
  3. The rebuild system may seem little bit creepy, but I am working to make it more logical.
public class DbBuilder
{
    public void Build()
    {
        var departments = new UmsBuildContext().Departments.ToList();
    }
}

or just take a look at this, http://stackoverflow.com/questions/4911329/ef-codefirst-ctp5-manually-drop-and-create-db

 

Find visual studio 2010 solution of framework 4 projects at the attachment. If you run the project it would create a "UMS" database with 3 tables, at the local machine. You can change it using app.config.

License

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

Share

About the Author

DiponRoy
Bangladesh Bangladesh
No Biography provided

You may also be interested in...

Pro
Pro

Comments and Discussions

 
GeneralMy vote of 5 Pin
linckon24-Sep-14 1:51
memberlinckon24-Sep-14 1:51 
GeneralRe: My vote of 5 Pin
diponsust24-Sep-14 7:42
memberdiponsust24-Sep-14 7:42 

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.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.161205.3 | Last Updated 29 Jul 2014
Article Copyright 2014 by DiponRoy
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid