views:

243

answers:

4

I have using blocks in each method of my repository. If I want to cross reference methods, it seems it would be against best practices to initialize another Datacontext What am i doing wrong? If I declare a Datacontext in the class instead of using blocks in methods will I not lose power to dispose ??

public IList<something> GetSomething()
{ 
   using (DB db=new DB())

   { ...GetListofSomethingElse(id)

   } 
}

public IList<somethingelse> GetListofSomethingElse(int id)
{ 
    using (DB db=new DB())
   {
     ... return IList 

   } 
}
+2  A: 

You can call .Dispose() on a class without using a 'using' statement - usually you'll do this in the Dispose method of your repository, if you've got one.

Erik Forbes
+2  A: 

The using statement is syntactic sugar. It compiles to a try/finally block with the Dispose() call in the finally section. It ensures that Dispose will be called even if an exception occurs.

Ed Swangren
+3  A: 

If you don't use a using statement, you can still dispose explicitly. Even if you don't dispose of the data context though, cross-referencing these methods will still create a new data context. That may or may not be a good thing, depending on your usage. Think about the state management aspect of the data context, and whether you want to isolate the methods from each other or not. If you want to avoid creating a new context all the time, overload the methods with versions which take the context as a parameter.

Note that you don't usually need to dispose of a data context, although I tend to dispose of anything implementing IDisposable.

Jon Skeet
+4  A: 

Actually, I think it is semantically (or how should I say that), not correct to create and dispose a datacontext in your repository.

I mean: if you open a new connection to the DB in each and every method of your repository, you're doing it wrong IMHO. This is too much fine grained. The repository class has no knowledge of the 'context' in which it is being used. Your repository should not be responsible for opening / closing connections or starting and committing transactions. Context is king, and the repository has no knowledge of the context in where it is being used. So, IMHO it is the responsability of the Application layer or service layer to open new DataContext objects, and closing / disposing them. (The same applies for transactions).

So, this is how I do it: (note that I do not use the Entity Framework, but I use NHibernate. I assume that the DataContext class in the EF is similar to the ISession in NHibernate):

using( ISession s = theSessionFactory.OpenSession() )
{
    ICustomerRepository cr = RepositoryFactory.GetCustomerRepository(s);

    Customer c1 = cr.GetCustomer(1);
    Customer c2 = cr.GetCustomer(2);

    // do some other stuff
    s.StartTransaction();

    cr.Save (c1);
    cr.Save (c2);

    s.Commit();

}

(This is not real world code offcourse; and it won't even compile since ISession doesn't have a Commit method. ;) Instead, the StartTransaction returns an ITransaction which has some kind of commit method, but I think you'll catch my drift. ;) )

Frederik Gheysels
interesting, i would prefer it this way, but is this not violating separation of Data Layer from business layer?
zsharp
How do you mean ?The ISession / DataContext is -imho- an infrastructure-concern. Infrastructure can be used in all layers. Also, the repository is a first class citizin in the 'domain'. My repository knows that it has to use a 'UnitOfWork' object which implements some interface.
Frederik Gheysels
what to do if i am assigning values to a custom object from the repository object while the data is coming in? as i have it now, the custom object is being assigned within the repository. the way you have it here, i would have to loop through results again in order to assign values.?
zsharp