Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I think you have a couple of changes to make:.</p> <ol> <li><p>Allow your DI container to inject a <code>UnitOfWork</code> instance into your Service classes in their constructors, and leave it out of your Controller altogether.</p></li> <li><p>If your DI container supports it (Ninject does, for example), configure your <code>UnitOfWork</code> to be managed on a per-request basis; this way your services will be handed a distinct <code>UnitOfWork</code> for each request, and you're all done. Or...</p></li> <li><p>If your DI container does not support per-request lifetimes, configure it to manage the <code>UnitOfWork</code> as a singleton, so every <code>Service</code> class gets the same instance. Then update your <code>UnitOfWork</code> to store its <code>Entities</code> object in a data store which stores objects on a per-request basis, for example in <code>HttpContext.Current.Items</code>, as described <a href="http://www.shubho.net/2011/01/using-httpcontextcurrentitems-as-data.html" rel="nofollow">here</a>.</p></li> </ol> <p><strong>Edit 1</strong></p> <p>Regarding where the <code>UnitOfWork</code> should be injected; I'd say the Service layer is the correct place. If you imagine your system as a series of layers where the outer layers deal with user interactions and the lower layers deal with data storage, each layer should become less concerned with users and more concerned with data storage. <code>UnitOfWork</code> is a concept from one of the 'lower-level' layers and Controller is from a higher-level layer; your <code>Service</code> layer fits between them. It therefore makes sense to put the <code>UnitOfWork</code> into the <code>Service</code> class rather than the <code>Controller</code>.</p> <p><strong>Edit 2</strong></p> <p>To elaborate on the <code>UnitOfWork</code> creation and it's relationship to <code>HttpContext.Current.Items</code>:</p> <p>Your <code>UnitOfWork</code> would no longer hold a reference to an <code>Entities</code> object, that would be done through the <code>HttpContext</code> object, injected into the <code>UnitOfWork</code> behind an interface like this:</p> <pre><code>public interface IPerRequestDataStore : IDisposable { bool Contains(string key); void Store&lt;T&gt;(string key, T value); T Get&lt;T&gt;(string key); } </code></pre> <p>The <code>HttpContext</code> object would then implement <code>IPerRequestDataStore</code> like this:</p> <pre><code>public class StaticHttpContextPerRequestDataStore : IPerRequestDataStore { public bool Contains(string key) { return HttpContext.Current.Items.Contains(key); } public void Store&lt;T&gt;(string key, T value) { HttpContext.Current.Items[key] = value; } public T Get&lt;T&gt;(string key) { if (!this.Contains(key)) { return default(T); } return (T)HttpContext.Current.Items[key]; } public void Dispose() { var disposables = HttpContext.Current.Items.Values.OfType&lt;IDisposable&gt;(); foreach (var disposable in disposables) { disposable.Dispose(); } } } </code></pre> <p>As an aside, I've called it <code>StaticHttpContextPerRequestDataStore</code> as it uses the static <code>HttpContext.Current</code> property; that's not ideal for unit testing (another topic altogether), but at least the name indicates the nature of its dependency.</p> <p>Your <code>UnitOfWork</code> then passes the <code>IPerRequestDataStore</code> it's given to each of its <code>Repository</code> objects so they can access the <code>Entities</code>; this means that no matter how many <code>UnitOfWork</code> instances you create, you'll use the same <code>Entities</code> object throughout a request because it's stored and retrieved in the <code>IPerRequestDataStore</code>.</p> <p>You'd have an abstract base <code>Repository</code> which would use its <code>IPerRequestDataStore</code> to lazy-load its <code>Entities</code> object like this:</p> <pre><code>public abstract class RepositoryBase : IDisposable { private readonly IPerRequestDataStore _dataStore; private PersonRepository personRepository; protected RepositoryBase(IPerRequestDataStore dataStore) { this._dataStore = dataStore; } protected BlogEntities Context { get { const string contextKey = "context"; if (!this._dataStore.Contains(contextKey)) { this._dataStore.Store(contextKey, new BlogEntities()); } return this._dataStore.Get&lt;BlogEntities&gt;(contextKey); } } public void Dispose() { this._dataStore.Dispose(); } } </code></pre> <p>Your <code>PeopleRepository</code> (for example) would look like this:</p> <pre><code>public class PeopleRepository : RepositoryBase, IPersonRepository { public PeopleRepository(IPerRequestDataStore dataStore) : base(dataStore) { } public Person FindById(int personId) { return this.Context.Persons.FirstOrDefault(p =&gt; p.PersonId == personId); } } </code></pre> <p>And finally, here's the creation of your <code>PeopleController</code>:</p> <pre><code>IPerRequestDataStore dataStore = new StaticHttpContextDataStore(); UnitOfWork unitOfWork = new UnitOfWork(dataStore); PeopleService service = new PeopleService(unitOfWork); PeopleController controller = new PeopleController(service); </code></pre> <p>One of the central concepts here is that objects have their dependencies injected into them via their constructors; this is generally accepted as good practice, and more easily allows you to compose objects from other objects.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload