Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>UPDATE: This approach works against NuGet current, but relies in an anomaly in the <code>InCallscope</code> implementation which has been fixed in the current Unstable NuGet packages. I'll be tweaking this answer in a few days to reflect the best approach after some mulling over. NB the high level way of structuring stuff will stay pretty much identical, just the exact details of the <code>Bind&lt;DbContext&gt;()</code> scoping will work. (Hint: <code>CreateNamedScope</code> in unstable would work or one could set up the Command Handler as <code>DefinesNamedScope</code>. Reason I dont just do that is that I want to have something that composes/plays well with <code>InRequestScope</code>) </p> <hr> <p>I highly recommend reading the <code>Ninject.Extensions.NamedScope</code> integration tests (seriously, find them and read and re-read them)</p> <p>The <code>DbContext</code> <strong>is</strong> a Unit Of Work so no further wrapping is necessary.</p> <p>As you want to be able to have multiple 'requests' in flight and want to have a single Unit of Work shared between them, you need to:</p> <pre><code>Bind&lt;DbContext&gt;() .ToMethod( ctx =&gt; new DbContext( connectionStringName: ConfigurationUtility.GetConnectionString() )) .InCallScope(); </code></pre> <p>The <code>InCallScope()</code> means that:</p> <ol> <li>for a given object graph composed for a single <code>kernel.Get()</code> <strong>Call</strong> (hence In <em>Call</em> Scope), everyone that requires an <code>DbContext</code> will get the same instance.</li> <li>the <code>IDisposable</code>.<code>Dispose()</code> will be called when a <code>Kernel.Release()</code> happens for the root object (or a <code>Kernel.Components.Get&lt;ICache&gt;().Clear()</code> happens for the root if it is not <code>.InCallScope()</code>)</li> </ol> <p>There should be no reason to use <code>InNamedScope()</code> and <code>DefinesNamedScope()</code>; You don't have long-lived objects you're trying to exclude from the default pooling / parenting / grouping.</p> <p>If you do the above, you should be able to:</p> <pre><code>var command = kernel.Get&lt;ICommand&gt;(); try { command.Execute(); } finally { kernel.Components.Get&lt;ICache&gt;().Clear( command ); // Dispose of DbContext happens here } </code></pre> <p>The Command implementation looks like:</p> <pre><code>class Command : ICommand { readonly IAccountRepository _ar; readonly IBlockedIpRepository _br; readonly DbContext _ctx; public Command(IAccountRepository ar, IBlockedIpRepository br, DbContext ctx){ _ar = ar; _br = br; _ctx = ctx; } void ICommand.Execute(){ _ar.Insert(a); _br.Insert(b); _ctx.saveChanges(); } } </code></pre> <hr> <p>Note that in general, I avoid having an implicit Unit of Work in this way, and instead surface it's creation and <code>Disposal</code>. This makes a Command look like this:</p> <pre><code>class Command : ICommand { readonly IAccountService _as; readonly IBlockedIpService _bs; readonly Func&lt;DbContext&gt; _createContext; public Command(IAccountService @as, IBlockedIpServices bs, Func&lt;DbContext&gt; createContext){ _as = @as; _bs = bs; _createContext = createContext; } void ICommand.Execute(){ using(var ctx = _createContext()) { _ar.InsertA(ctx); _br.InsertB(ctx); ctx.saveChanges(); } } </code></pre> <p>This involves no usage of <code>.InCallScope()</code> on the <code>Bind&lt;DbContext&gt;()</code> (but does require the presence of <a href="https://github.com/ninject/ninject.extensions.factory/wiki" rel="nofollow"><code>Ninject.Extensions.Factory</code>'s <code>FactoryModule</code></a> to synthesize the <code>Func&lt;DbContext&gt;</code> from a straightforward <code>Bind&lt;DbContext&gt;()</code>.</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.
    1. COI can't use singleton .. cause the services are located in commands which are created per threads. This is a game server. But the InNamedScope seem to be what i was looking for.. when the scope end does others instances (see above example added) which are transcient but par of the instance that has a scope get disposed somehow ? or do i have to call Release after the service is executed ? What happen if the parent instance get GC ?
      singulars
    2. COThanks that a very nice example. Just wondering.. what happen if the composition root isn't exactly like that ? I mean i do not have access to the kernel.. except if i use the service locator. Any idea ? It all start from a singleton.. I am integrating my architecture over some other library.. and the only entry point i found is the commands (server queries where i inject my services). So basically they are all instancied once.. and requests are redirected to them.
      singulars
    3. CO@Rushino Not sure what you mean here. Perhaps a separate question with an illustration of your constraints might be in order. Firstly, you can use https://github.com/ninject/ninject.extensions.factory/wiki to give appropriately constrained access to the creation of Command Handlers etc. at the right point in your processing cycle. e.g. `kernel.Get<ICommand>();` can become you having an `ICommandFactory` (with an `ICommand CreateCommand()`) provided to your `ServerQueryProcessor` 'server query' implementation. In other words, your query processor becomes a Composition Root.
      singulars
 

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