Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET / ASP.NET4

An Absolute Beginner's Tutorial for understanding Entity Framework's Code First Approach in ASP.NET MVC

4.88/5 (52 votes)
18 Nov 2013CPOL7 min read 280.1K   8.5K  
In this article we will discuss about entity framework code first approach.

Introduction

In this article we will discuss about entity framework code first approach. We will see what are the benefits of code first approach. We will also create a sample ASP.NET MVC application using code first approach.

Background

Before starting this article we need to understand the shift in the way the modern applications are being architectured. Traditionally we have been designing and developing data centric applications(Data Driven Design). What this means is that we used to think about what data is required to fulfill our business needs and then we build our software bottom up from the database schema. This approach is still being followed for many applications and for such applications we should use the Entity framework database first approach. 

The alternative way of designing or architecturing our application is by using Domain centric approach(Domain Driven Design). In this approach we think in terms of entities and models that we needed to solve a particular business problem. Now if some of these models need persistence we can keep them in a database or any data store. In this approach we design our models in such a way that they can be stored/persisted anywhere. In other words we create persistent ignorant models and write persistence logic separately. Entity framework code first approach is for creating application's models using Domain centric approach and then they can be persisted later.

So Entity framework code first approach enables us to write Plain Old CLR Objects(POCOs) for our models and then let us persist them in a data store by defining a DbContext class for our model classes. Few of the benefits of using this approach are:

  • Ability to support domain driven design.
  • Ability to start development faster(without waiting for the database and to be ready and mature).
  • Model classes are lot cleaner since there is no(or very minimal) persistence related code in the models.
  • The persistence layer can be changed without having any impact on the models.

Note: This article is meant for the absolute beginner's who have never worked with the code first approach or who are unaware of this approach. So the article only contains the introductory information and code to explain the concept and get the reader started. This article will not be discussing the advanced topics and best practices related to code first approach.

Using the code

Let us try to understand how we can implement the code first approach by creating a small toy application. The application that we will be creating is a small books information website which will

  1. Show a list of books.
  2. Show the details of selected book.
  3. Adding new books.
  4. Deleting Books.
  5. Editing books information.
  6. Users should also be able to add review comments for any given book.

Based on the above problem definition we need 2 models. One for Book and another for the Reviews. To get started lets go ahead and add a nuget package reference to the Entity framework.

 Image 1

Now we are all set to start work on our application.

Creating the POCOs

Let us now go ahead and create these models without worrying about the persistence.

public class Book
{
    public int BookID { get; set; }
    public string BookName { get; set; }
    public string ISBN { get; set; }
}

public class Review
{
    public int ReviewID { get; set; }

    public int BookID { get; set; }
    public string ReviewText { get; set; }
}

In our Model classes we have defined the properties that we want to keep in our models. But there are few things which we have not done so far. There is a one to many relationship between these models. So we need to take that into account for our models. Also, If we want to hint the database generation module about the persistence information like table names, key columns etc. We can do that too in our model classes. So with these changes our model classes will look like.

C#
[Table("Books")] // Table name
public class Book
{
    [Key] // Primary key
    public int BookID { get; set; }
    public string BookName { get; set; }
    public string ISBN { get; set; }

    // This is to maintain the many reviews associated with a book entity
    public virtual ICollection<Review> Reviews { get; set; }
}

[Table("Reviews")] // Table name
public class Review
{
    [Key]
    public int ReviewID { get; set; }

    [ForeignKey("Book")]
    public int BookID { get; set; }
    public string ReviewText { get; set; }

    // This will keep track of the book this review belong too
    public virtual Book Book { get; set; }
}

Creating the Context class

Now we have our model classes ready. Next we need to create a DBContext object that will be responsible for performing all the CRUD operations on these models. Let us go ahead and create the DBContext class for these models.

C#
public class BooksDbContext : DbContext
{
    public DbSet<Book> Books { get; set; }
    public DbSet<Review> Reviews { get; set; }
}

The above defined context class is capable of performing CRUD operations on Book and Review model since it has the DbSet defined for both of them.

Setting the database and location 

Now with the DbContext class ready the only question left for us that where this data will get stored. Since ages, we have been using ConnectionStrings to specify the connection to the database. In this case also we can use

ConnectionString
too to specify the location and meta data of the database that the DbContext class should use. Let us see if we need to create the database in the App_Data folder, how the ConnectionString will look like:

XML
<connectionStrings>
    <add name="BooksDbContext" connectionString="data source=.\SQLEXPRESS;attachdbfilename=|DataDirectory|\sampleDb.mdf;integrated security=True;user instance=True;multipleactiveresultsets=True;" providerName="System.Data.SqlClient" />
</connectionStrings>

The important thing to notice here is that the name of the connectionString is same as the DbContext class that we have created. If we keep the name of the connectionString same as the DbContext class the corresponding DbContext class will use the connectionString to persist the data. This is on the lines of "Convention over configurations". But this is also flexible so that we have the possiblity of giving custom names to the connectionStrings i.e. If we need to give any other name to the connectionString or use some already defined connectionString with the DbContext class then we need to pass the connectionString name in the base class constructor of our DbContext class.

Testing the Code first Models and Context

To test the above defined models let us create a simple ASP.NET MVC controller that will perform the CRUD operations on the Book entity. 

C#
public class BooksController : Controller
{
    BooksDbContext context = new BooksDbContext();

    public ActionResult Index()
    {
        List<book> books = context.Books.ToList();
        return View(books);
    }

    public ActionResult Details(int id)
    {
        Book book = context.Books.SingleOrDefault(b => b.BookID == id);
            
        if (book == null)
        {
            return HttpNotFound();
        }
        return View(book);
    }

    public ActionResult Create()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Create(Book book)
    {
        if (ModelState.IsValid)
        {
            context.Books.Add(book);
            context.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(book);
    }

    public ActionResult Edit(int id)
    {
        Book book = context.Books.Single(p => p.BookID == id);
        if (book == null)
        {
            return HttpNotFound();
        }
        return View(book);
    }

    [HttpPost]
    public ActionResult Edit(int id, Book book)
    {
        Book _book = context.Books.Single(p => p.BookID == id);

        if (ModelState.IsValid)
        {
            _book.BookName = book.BookName;
            _book.ISBN = book.ISBN;

            context.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(book);
    }

    public ActionResult Delete(int id)
    {
        Book book = context.Books.Single(p => p.BookID == id);
        if (book == null)
        {
            return HttpNotFound();
        }
        return View(book);
    }

    [HttpPost]
    public ActionResult Delete(int id, Book book)
    {
        Book _book = context.Books.Single(p => p.BookID == id);
        context.Books.Remove(_book);
        context.SaveChanges();
        return RedirectToAction("Index");
    }

    protected override void Dispose(bool disposing)
    {
        context.Dispose();
        base.Dispose(disposing);
    }
}
</book>

In this model we are using the Context class to perform the CRUD operations on the Book entity. (To know how to use DbContext class to perform CRUD operations refer: An Introduction to Entity Framework for Absolute Beginners[^]) 

Adding the Views

Let us generate the strongly types scaffold views for this controller using the ASP.NET MVC view generations wizard. (To learn mode about default scaffold controller and views in ASP.NET MVC refer: An Absolute Beginner's Tutorial on ASP.NET MVC for Web Forms Developers[^]) 

List of Books

 Image 2

Details of selected Book

 Image 3

Create a new Book Entry

Image 4 

Edit a Book entry

 Image 5

Delete a Book

 Image 6

Lets run and test the application

With this we have an application ready with the CRUD operation on a Books entity using the Entity framework code first approach. Let try to run this application. On first run it will now show any data but it will create a new database at the location specified in the connectionString.

Image 7 

Create a new Book Entry

Image 8 

Details of selected Book

Image 9 

Edit a Book entry

Image 10 

Delete a Book

Image 11 

List of Books

Image 12 

Managing enitity relationships - Adding Book Reviews

Let us modify the Book details view to show all the reviews associated with the book too.

Image 13 

And now we will create a controller for reviews to add the reviews to a book. For now let us only implement the Create method in this controller.

C#
public class ReviewsController : Controller
{
    BooksDbContext context = new BooksDbContext();

    public ActionResult Create(int id)
    {            
        Book book = context.Books.SingleOrDefault(b => b.BookID == id);
        ViewBag.bookName = book.BookName;

        Review review = new Review();
        review.BookID = id;

        return View(review);
    }

    [HttpPost]
    public ActionResult Create(Review review)
    {
        try
        {
            if (ModelState.IsValid)
            {
                Book book = context.Books.SingleOrDefault(b => b.BookID == review.BookID);
                book.Reviews.Add(review);
                context.SaveChanges();
                return RedirectToAction("Details", "Books", new { id = book.BookID });
            }
            return View();
        }
        catch
        {
            return View();
        }
    }
}

We will now add a simple view to add reviews to the books.

Image 14 

And once added these reviews will be available to on the books details page.

Image 15 

Now we have a simple application containing two entities with 1 to many relationship persisting the data in a database using the Entity framework code first approach.

Note: Before building the sample project, open the nuget package manager and restore the missing packages.

Point of interest 

This article was written for the absolute beginner's who have no idea about the code first approach. This article presents the reader with some introductory notes on what is code first approach and how we can implement a simple ASP.NET MVC application with code first approach. What we have not talked about in this article but is still very important for this topic is the updation of database schema whenever we are changing the models i.e. database migrations.

Note: We have not used any patterns like repository and unit of work in this article since the main idea of the article was to introduce the reader to the code first approach of entity framework. Most experiences programmer will find this article very basic and not much helpful. But I hope this has been informative to all the absolute beginner's to Entity framework code first.

History 

  • 18 November 2013: First version

License

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