Entity Framework for Beginners Part 3 – DbContext

This post is part 3 of 4 covering Entity Framework Code-First for Beginners.

  1. Part 1 – Setting Up Entity Framework Code-First for Beginners
  2. Part 2 – Migrations in Entity Framework Code-First
  3. Part 3 – DbContext
  4. Part 4 – Entity Framework Code-First Extras

The DbContext is Entity Framework’s keystone. It is where all the action takes place. In this post, I will show you how to use it and some of the out-of-the-box behaviors the DbContext has and how to use it in your own applications. If you haven’t been following along with the series, start by downloading the sample project here and reading part 1 above.

As I mentioned, the DbContext is the central hub of Entity Framework in our applications. It houses our model classes and is what we will use to access the data in our application. In order to access those model classes, we need to declare an instance of the DbContext. We also need a strategy here. Unless you want to keep writing the same code over and over, we need a central location that we can use in order to access our data without a bunch of duplication in our code base. There are a couple of different ways we can go about this but the Repository design pattern is a popular way to go and is fairly straightforward to implement so we will use that. Some of the alternatives are GenericRepository (which is lightly covered at the end of this post) and the Command Query Separation pattern or it’s more complicated cousin pattern Command Query Responsibility pattern.

Lets add a new class to the Code\DataAccess folder named ContactRepository.cs. We need to create an instance of the DbContext in our repository. I am also going to group the constructors here. If you notice, there is a second constructor that allows us to pass the DbContext into this repository. If the application expands and a second repository is added, business logic that sits on top of this may want to combine the results from the new repository and from ContactRepository. If you are returning IQueryable objects from your repositories (you should), you can’t combine the results from two different DbContexts even if they are copies of the same DbContext and both repositories will have their own copy.

private ContactManagerDbContext _context = null;

public ContactRepository()
{
    _context = new ContactManagerDbContext();
}

public ContactRepository(ContactManagerDbContext context)
{
    _context = context;
}

Now that we have our context wired up, let’s take a look at the code to perform CRUD operations and to return a list of Contacts.

//Return an IQueryable<Contact> of all contacts.
public IQueryable<Contact> GetContacts()
{
    return _context.Contacts;
}

//Return a single contact
public Contact GetContact(int contactId)
{
    return GetContacts().Single(c => c.ID == contactId);
}

//This method assumes the contact is already attached. Save the changes to the database.
public bool UpdateContact(Contact contact)
{
    try
    {
        _context.SaveChanges();
        return true;
    }
    catch (Exception ex)
    {
        LogException(ex);
        return false;
    }
}

//Delete the contact.
public bool DeleteContact(Contact contact)
{
    try
    {
        _context.Contacts.Remove(contact);
        _context.SaveChanges();
        return true;
    }
    catch(Exception ex)
    {
        LogException(ex);
        return false;
    }
}

//Add a new contact
public bool AddContact(Contact contact)
{
    try
    {
        _context.Contacts.Add(contact);
        _context.SaveChanges();
        return true;
    }
    catch(Exception ex)
    {
        LogException(ex);
        return false;
    }
}

As you might imagine, this code would get very repetitive if we have three or more repositories that are similar to this one. This is where the GenericRepository comes in. Now, before you get too excited, understand that there are drawbacks to the GenericRepository pattern. It is an a real pain to unit test. Most people wrap the GenericRepository in a UnitOfWork pattern that allows them to more easily test. It is up to you to determine just how much abstraction you need. Below is the code for a very similar GenericRepository to the one above.

public class GenericRepository
{
    private ContactManagerDbContext _context = null;

    public GenericRepository()
    {
        _context = new ContactManagerDbContext();
    }

    public GenericRepository(ContactManagerDbContext context)
    {
        _context = context;
    }

    public IQueryable<T> GetAll<T>() where T : class
    {
        return _context.Set<T>();
    }

    public bool Update<T>(T item) where T : class
    {
        try
        {
            _context.Set<T>().Attach(item);
            _context.SaveChanges();
            return true;
        }
        catch(Exception ex)
        {
            LogException(ex);
            return false;
        }
    }

    public bool Delete<T>(T item) where T : class
    {
        try
        {
            _context.Set<T>().Remove(item);
            _context.SaveChanges();
            return true;
        }
        catch(Exception ex)
        {
            LogException(ex);
            return false;
        }
    }

    public bool Add<T>(T item) where T : class
    {
        try
        {
            _context.Set<T>().Add(item);
            _context.SaveChanges();
            return true;
        }
        catch(Exception ex)
        {
            LogException(ex);
            return false;
        }
    }

    private void LogException(Exception ex)
    {

    }
}

There are a couple of issues for the code above but I don’t want to spend a whole lot of time on it. There isn’t a SaveChanges() method available outside the class and if you are performing a long list of operations, you are saving after each and every one of those operations.

Hopefully, this post gives you a good idea of how to use Entity Framework in your own applications. The next post will give a few helpful tidbits on the usage of Entity Framework and the series will wrap up.

 

Comments 2

  1. Pingback: Entity Framework for Beginners Part 2 – Migrations | Edumacate Blog

  2. Pingback: Entity Framework for Beginners Part 4 – Extras | JasonBentley.net Blog

Leave a Reply

Your email address will not be published.