views:

497

answers:

2

Is there any potential problem in setting datacontext as property like this:

repository

public Repository()
{ 
    public DataContext dc {get;set;}

    public GetOrders(int id)
       { ...from dc.Orders...}
}

service layer:

public GetNewOrders()
   {
       ....
       Repository rep=new Repository();
       using {DataContext dc=new DataContext())
        { 
           rep.dc=dc;
           rep.GetOrders(id);
        }
    }
+2  A: 

In DDD, you're missing the bigger picture here by referencing the concret classes. You are not interfacing between the Repository and "Services layer" by best practices. If you must have DataContext injected into the Repository, I would recommend refactoring to:

public interface IRepository
{
  IList<Orders> GetNewOrders();
}
public Repository : IRepository
{
  private DataContext _dataContext;
  public Repository(DataContext dataContext)
  {
    _dataContext = dataContext;
  }
  public IList<Orders> GetNewOrders()
  {
    // perform your actions on _dataContext here
  }
}

The better solution would be to let the Repository handle the DataContext on its own - keeping the seperation of concert valid by masking the underlying requirements:

public interface IRepository
{
  IList<Orders> GetNewOrders();
}
public Repository : IRepository
{
  private DataContext _dataContext;
  public Repository(String connectionString)
  {
    _dataContext = new DataContext(connectionString);
  }
  public IList<Orders> GetNewOrders()
  {
    // perform your actions on _dataContext here
  }
}

If you must keep control of the DataContext (or another class) yourself (perhaps you want to keep a static reference around, or change settings based on an WebRequest, etc), you you will need to use a "Factory".

The factory would look something like this:

public static class DataContextFactory
{
  public static DataContext GetInstance()
  {
    // return either a static instance, 
    // or threaded instance, or whatever
    // your preference is here
    // 
  }
}

That way, you have full control over how the instance of DataContext is controlled outside and away from your "Services" layer.

"How to access the IRepository?" you may ask?

Your services layer would do something like:

public void GetNewOrdersForServices()
{
  // Not recommended!
  //      IRepository repo = new Repository()
  //
  // The following is recommended instead; because, it removes the
  // the Concret reference from your Services layer completely!
  //
  IRepository repo = ServiceLocator.InstanceOf<IRepository>();
  IList myList = repo.GetNewOrders();
}

If you are not fimilar with the service locator concepts, check out Castle Windsor as it Encapsulates just about all your needs.

eduncan911
where and how to dispose of datacontext?
zsharp
Dispose of it immediately after using it. Put another way, only use it in a using block.
flipdoubt
Since the instance of DataContext is private to the instance of IRepository, IDisposal takes care of the garbage collection when IRepository is distroyed. Therefore, you would not have to handle it. If you DO want control over it, use using() in the DataContextFactory above.
eduncan911
Again, with the DataContextFactory "factory" pattern, you have control over the LifeStyle of that object (i.e. the DataContext object in this case) with the InstanceOf pattern. Keep a static reference around. Use using() for only new threads, etc. You are in control at that level.
eduncan911
+3  A: 

From what I have read, using the DataContext "for more than one business conversation is usually the wrong thing to do." Scroll down to the Why Is This Important? section for the quote. Due to caching and other factors, you should consider your DataContext stale immediately. From that, it is safe to say you don't want to keep the DataContext as a property that is reused by all your methods. Using Eric Duncan's suggestion, you will want to pass in some kind of DataContext factory to get a new context for each query.

For a discussion focused on the DataContext, the APress Pro LINQ book has an entire chapter on the DataContext, the very last page of which also advises you to "consider the DataContext stale immediately."

flipdoubt
Thanks flipdoubt! Voted for your answer, as that's a good reference/link.
eduncan911
Thanks. I added some more links.
flipdoubt
But it is in a using block in the service layer, so it would be "stale" after the call to the repository.
zsharp
If you take the quotes literally, then it is stale before you even use it, so you should use and get rid of it ASAP. If you keep your using block nice and tight as in your example, "after the call to the repository" the using block ends, so you should be good.
flipdoubt
No +1? Aw shucks.
flipdoubt
Thanks, Eric. I gave you one too.
flipdoubt
+1 for hitting it right on the head
JoshJordan