views:

191

answers:

3

for example:

class repository {

     private DataContext db = new DataContext();

     public IQueryable<Blah> someMethod(int id){
         return from b in db.Blah ... select b;
}

     public IQueryable<Blah> someMethod2(int id){
         return from b in db.Blah ... select b;
}

     public IQueryable<Blah> someMethod3(int id){
         return from b in db.Blah ... select b;
}

}

OR

Should we make a new DataContext WITHIN each of those methods?

I think we are having some errors once user load increases due to us only having ONE DataContext per Repository instance, is this an accurate assumption?

+1  A: 
Rippo
That has to do with opening and closing connection. Linq-to-sql and Entity Framework close the connection right after completing the query. Combined with connection pooling this makes for a pretty fast and scalable solution. Note that connections are far shorter lived than the context itself.
Sander Rijken
So the data context follows the pattern of opening the connection late and closing early? My last point regarding the sql profile still stands.
Rippo
Yeah, and I also agree with the profiler part.
Sander Rijken
+3  A: 

See also the answer to this question.

In short, especially if you are using a repository pattern, you should create and dispose of a datacontext for each unit of work. Typically I use something like:

public someclass someMethod(int id)
{
    using (var db = new SomeDataContext())
    {
        return db.FindMyClass(id);
    }
}
Eric King
+1 beat me to it. ;)
Chris Lively
What do you mean SomeDataContext()? Does this mean a class you made that inherits from DataContext? So then you make the methods for getting data that you need inside of there instead of in the Repository?
shogun
No, that's the actual datacontext, not a derived class. Sorry if the fake naming was confusing.
Eric King
+1  A: 

What I did personally, is make the repository disposable. You then get constructs like:

void DeleteCustomer(int id)
{
    using(var repos = GetRepos())
    {
        var customer = repos.GetAll<Customer>().Single(x => x.Id == id);
        repos.Delete(customer);
        repos.SaveChanges();
    }
}

This can be implemented by creating the context in the repository ctor, and disposing it in the Dispose() implementation.

You need to make sure you're not adding/changing/delete objects and selecting from the same context. A context is made to 'last' a unit of work.

You need to be careful of stuff like this though:

IQueryable<Customer> GetCustomers()
{
    using(var repos = GetRepos())
    {
        return repos.GetAll<Customer>();
    }
}

void Test()
{
    // This will throw an exception, because it extends the linq query
    // while the context is disposed.
    var customers = GetCustomers().Where(x => x.Id == 123); 
}

In that case it's better to move the repository outside as much as possible:

IQueryable<Customer> GetCustomers(MyRepository repos)
{
    return repos.GetAll<Customer>();
}

void Test()
{
    using(var repos = ...)
    {
        var customers = GetCustomers(repos).Where(x => x.Id == 123); 
    }
}
Sander Rijken
What benefits does this give you? From my experience if you cant guarantee that you may want to do more work on the context then using "using" can throw unexpected runtime errors.
Rippo
Yep, you could consider skipping the using altogether. I think that's rather safe, because it closes the connection as soon as it's done with it (so it doesn't keep a connection open), and the GC will clear it when the context + query falls out of scope.
Sander Rijken
+1 for nice explanation. thanks for your comments
Rippo