Question

I'm wondering what the differences are regarding performance and general best practices when connecting to db using context classes for a web site. What is the best way to go when considering these two different approaches:

public class Repository()
{
    Private Context context;

    public List<User> GetUsers()
    {
        return this.context.Users.ToList();
    }

or

public class Repository()
{        
    public List<User> GetUsers()
    {
        using (Context context = new context())
        {
            return context.Users.ToList(); 
        }
    }
 }

And does it matter if it returns the result as a List or as IEnumerable?

Was it helpful?

Solution 2

Although you already accepted an (altogether acceptable) answer that addresses lifetime issues, I think the most important aspect has only be skimmed in Chris's answer. The most important reason why (IMHO) it should be option 1 is composability. (But an important assumption is that in option 1 the repository receives a context in its constructor, so this context can be shared by multiple repositories in one use case).

Suppose you want to join two entities in one query:

from u in repo1.GetUsers()
join r in repo2.GetRoles() on u.UserId equals r.UserId
where u.UserId = ...

With option 2 this would execute separate queries for users and roles, because two DbSets from different contexts can only be combined in memory. With option 1 (and some modifications) this will fire one composed query with a SQL join.

What you'll need do do additionally, is return IQueryable in stead of List, i.e. just return context.Users.

Also, with option 2, if you make changes to entities from different repositories it is much more elaborate to commit them in one transaction. (You need SaveChanges() calls in each context, wrapped in a TransactionScope).

A bit off-topic, but too relevant to omit is the fact that the modified option 1 would probably leave you with a very, very thin middleman between DbSets and your application code. You may decide that this repository layer doesn't add anything useful and ditch it altogether.

OTHER TIPS

Copy from MSDN

Lifetime

The lifetime of the context begins when the instance is created and ends when the instance is either disposed or garbage-collected. Use using if you want all the resources that the context controls to be disposed at the end of the block. When you use using, the compiler automatically creates a try/finally block and calls dispose in the finally block.

using (var context = new ProductContext())
{    
    // Perform data access using the context
}

Here are some general guidelines when deciding on the lifetime of the context:

When working with long-running context consider the following: As you load more objects and their references into memory, the memory consumption of the context may increase rapidly. This may cause performance issues. Remember to dispose of the context when it is no longer required. If an exception causes the context to be in an unrecoverable state, the whole application may terminate. The chances of running into concurrency-related issues increase as the gap between the time when the data is queried and updated grows. When working with Web applications, use a context instance per request. When working with Windows Presentation Foundation (WPF) or Windows Forms, use a context instance per form. This lets you use change-tracking functionality that context provides.

Definitely the second approach.
Constructing a DbContext is almost a no-op. The expensive thing to do is creating (not establishing) a connection to the Db, and this happens only once due to connection pooling. On the other hand, keeping a connection open for a longer time is a bad idea (among other things, it is quite resource-intensive) and can cause various other problems (e.g. connection breaks due to network errors).

Use the first version. If you need to call multiple methods on your repository, you will only initialize your context once, instead of initializing it over and over again inside every method. Also, by using a backing field, you also give yourself the option of leveraging dependency injection, which is a powerful concept to keep your application decoupled, flexbile, testable, and maintainable:

http://www.asp.net/mvc/tutorials/hands-on-labs/aspnet-mvc-4-dependency-injection

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top