NHibernate and the Unit of Work Patternhttp://nhforge.org/wikis/patternsandpractices/nhibernate-and-the-unit-of-work-pattern.aspxen-USCommunityServer 2008.5 (Build: 30929.2835)NHibernate and the Unit of Work Patternhttp://nhforge.org/wikis/patternsandpractices/nhibernate-and-the-unit-of-work-pattern.aspxTue, 23 Sep 2008 20:21:17 GMT45f813f2-f1c4-4eda-a619-288e3cadc793:35gabriel.schenkerhttp://nhforge.org/wikis/patternsandpractices/nhibernate-and-the-unit-of-work-pattern/comments.aspx<h1>Part 1</h1> <h2>Introduction</h2> <p>Martin Fowler <a href="http://martinfowler.com/eaaCatalog/unitOfWork.html">writes</a>: </p> <p>&quot;When you&#39;re pulling data in and out of a database, it&#39;s important to keep track of what you&#39;ve changed; otherwise, that data won&#39;t be written back into the database. Similarly you have to insert new objects you create and remove any objects you delete.&quot;</p> <p>and</p> <p>&quot;A <b>Unit of Work</b> keeps track of everything you do during a <i>business transaction</i> that can affect the database. When you&#39;re done, it figures out everything that needs to be done to alter the database as a result of your work.&quot;</p> <p>In NHibernate we have the <b>Session</b> object which is a Unit of Work (UoW) container. The session object keeps track of all objects you load, new objects you add, existing objects you delete and changes you make to any of these objects. Only when <b>flushing</b> the session will the database be altered (that is: will the necessary create, update and delete statements be sent to the database).</p> <p>Now, working directly with the NHibernate session object makes absolute sense. But some times you rather want to abstract the data manipulation interface from a specific infrastructure implementation &agrave; la NHibernate.</p> <p><b>Note</b>: most of the design ideas and implementation details presented here originate from <a href="http://www.ayende.com/">Ayende</a>&#39;s UnitOfWork implemented in the <b>Rhino.Commons</b> which you can get <a href="http://rhino-tools.svn.sourceforge.net/svnroot/rhino-tools/trunk">here</a>.</p> <h2>Design and Implementation (TDD)</h2> <h3>Some thought about TDD</h3> <p>I want to implement a UnitOfWork pattern for NHibernate and I want to do it by using <a href="http://en.wikipedia.org/wiki/Test-driven_development">TDD</a>. For a beginner (like I was myself not so long ago) it seems unnatural at the beginning. We introduce a huge overhead you might think. You might also think that we have to write at least double the code as when doing the development without TDD. But wait until you have to start to debug your application... or until the customer wants to have something changed in the application... or until you have to re-factor you application... Then you will immediately see and feel the benefits of a good test coverage.</p> <h3>Attention: Multi-Threading ahead</h3> <p>Please not that the implementation presented here is strictly <b>NOT</b> thread safe!!! I want to reduce the complexity of this first implementation. But <b>I promise</b> that in a following post I&#39;ll show you how to make the implementation of the unit of work pattern thread safe and thus useful for e.g. Web scenarios.</p> <h3>The UnitOfWork Class</h3> <p>To start with: I want to have an easy way to <b>start</b> a new UoW, in any place of my application have access to the <b>current</b> UoW and <b>commit</b> the <i>business transaction</i> represented by my UoW. We can do this with a static class called UnitOfWork</p> <p><a><img src="/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/nhibernate.UoW/UoW-UoW_2D00_class.png" alt="" /><br /></a></p> <p>The method start creates and returns an instance of a <b>UnitOfWorkImplementor</b> class which implements the interface <b>IUnitOfWork</b>. As you can see then interface IUnitOfWork inherits from IDisposable. So we can define that the <i>business transaction</i> is ended when the UoW is disposed. Now, if we do nothing else then nothing should happen, that is no changes should be propagated to the database. To commit a <i>business transaction</i> we have to explicitly call a method of the UoW. Let&#39;s call this method <b>TransactionalFlush</b>. In doing so all changes recorded by the UoW are committed to the database in one go.</p> <p>Now let&#39;s start to implement this! We are doing TDD, aren&#39;t we? So we will write our first test (if you are not sure how to best setup a new solution for TDD please consult <a href="http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/04/06/how-to-setup-a-new-solution.aspx">this</a> post). I define a new solution with two projects as follows</p> <p><a><img src="/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/nhibernate.UoW/UoW-Solution.png" alt="" /><br /></a></p> <p>Add a class UnitOfWork_Fixture.cs to the test project and implement the first test like this</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[TestFixture]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> UnitOfWork_Fixture</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">readonly</span> MockRepository _mocks = <span style="color:#0000ff;">new</span> MockRepository();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> [Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_Start_UnitOfWork()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> IUnitOfWork uow = UnitOfWork.Start();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Of course this test will not compile since you don&#39;t have the types UnitOfWork and IUnitOfWork defined yet. Let <a href="http://www.jetbrains.com/resharper/">Resharper</a> create them for you (or implement them by hand)</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">class</span> UnitOfWork</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> IUnitOfWork Start()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">throw</span> <span style="color:#0000ff;">new</span> NotImplementedException();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> IUnitOfWork Current { get; <span style="color:#0000ff;">private</span> set; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">interface</span> IUnitOfWork : IDisposable</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Now the test will compile but it will fail! Of course, you haven&#39;t implemented the Start method so far. In this method we must now create a new UoW and return it to the caller. A UoW is a complex beast and should therefore be constructed in a factory. So let&#39;s define a factory Interface IUnitOfWorkFactory with a method Create which returns a UoW implementing the interface IUnitOfWork.</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">interface</span> IUnitOfWorkFactory</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> IUnitOfWork Create();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>since we want to test our UnitOfWork class in isolation we have to mock all other dependencies line the unit of work factory. I&#39;ll use <b>Rhino.Mocks</b> as my mocking framework (Please refer to documentation <a href="http://www.ayende.com/wiki/Rhino+Mocks+Documentation.ashx">here</a>). I want to test that when calling the start method of the UnitOfWork class the factory gets called. So I extend my test function</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_Start_UnitOfWork()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var factory = _mocks.DynamicMock&lt;IUnitOfWorkFactory&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var unitOfWork = _mocks.DynamicMock&lt;IUnitOfWork&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#008000;">// brute force attack to set my own factory via reflection</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var fieldInfo = <span style="color:#0000ff;">typeof</span>(UnitOfWork).GetField(<span style="color:#006080;">&quot;_unitOfWorkFactory&quot;</span>, </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> BindingFlags.Static | BindingFlags.SetField | BindingFlags.NonPublic);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> fieldInfo.SetValue(<span style="color:#0000ff;">null</span>, factory);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">using</span>(_mocks.Record())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Expect.Call(factory.Create()).Return(unitOfWork);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">using</span>(_mocks.Playback())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var uow = UnitOfWork.Start();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>In the first two lines of code I mock the external dependencies of the UnitOfWork class. Then I do something you should not do very often (but I have good reasons doing so here and I promise it&#39;s the only time I&#39;ll do it in this project...). I set a private field of the UnitOfWork class with a value by using reflection. I could implement a public setter in the class but as I would only need it for this test and I want to keep the class interface as simple as possible I chose to do it via reflection.</p> <p>In the&nbsp; record phase I define my expectation (namely that the factory create method is called) and in the playback phase I invoke the Start method which I want to test. The test will compile but fail to execute. I have not yet defined the private static field _unitOfWorkFactory and I also do not call the factory. So let&#39;s modify our code...</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">class</span> UnitOfWork</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">static</span> IUnitOfWorkFactory _unitOfWorkFactory;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">static</span> IUnitOfWork _innerUnitOfWork;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> IUnitOfWork Start()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _innerUnitOfWork = _unitOfWorkFactory.Create();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> _innerUnitOfWork;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> IUnitOfWork Current { get; <span style="color:#0000ff;">private</span> set; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>now the test will pass.</p> <p>Since in all our test regarding the UnitOfWork class we will always need it with an injected factory we define a new test fixture with a context setup for our specific needs. We put the respective code in the <b>SetupContext</b> and <b>TearDownContext</b> methods</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[TestFixture]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> UnitOfWork_With_Factory_Fixture</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">readonly</span> MockRepository _mocks = <span style="color:#0000ff;">new</span> MockRepository();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">private</span> IUnitOfWorkFactory _factory;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> IUnitOfWork _unitOfWork;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> [SetUp]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> SetupContext()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _factory = _mocks.DynamicMock&lt;IUnitOfWorkFactory&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _unitOfWork = _mocks.DynamicMock&lt;IUnitOfWork&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#008000;">// brute force attack to set my own factory via reflection</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var fieldInfo = <span style="color:#0000ff;">typeof</span>(UnitOfWork).GetField(<span style="color:#006080;">&quot;_unitOfWorkFactory&quot;</span>,</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> BindingFlags.Static | BindingFlags.SetField | BindingFlags.NonPublic);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> fieldInfo.SetValue(<span style="color:#0000ff;">null</span>, _factory);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _mocks.BackToRecordAll();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> SetupResult.For(_factory.Create()).Return(_unitOfWork);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _mocks.ReplayAll();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> [TearDown]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> TearDownContext()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _mocks.VerifyAll();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p><b>Note</b>: in the second last line of the <b>SetupContext</b> method we define that each time the method Create of the factory object is called (by the UnitOfWork Start method) we want it to return our predefined mocked _<b>unitOfWork</b> instance.</p> <p>Trying to start a UoW if there is already one active should throw a meaningful exception. This is the test</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Starting_UnitOfWork_if_already_started_throws()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> UnitOfWork.Start();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">try</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> UnitOfWork.Start();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">catch</span> (InvalidOperationException ex)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> { }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>As a consequence we have to extend our Start method in the UnitOfWork class</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> IUnitOfWork Start()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">if</span> (_innerUnitOfWork != <span style="color:#0000ff;">null</span>)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">throw</span> <span style="color:#0000ff;">new</span> InvalidOperationException(<span style="color:#006080;">&quot;You cannot start more than one unit of work at the same time.&quot;</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _innerUnitOfWork = _unitOfWorkFactory.Create();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> _innerUnitOfWork;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>Now I have another problem: After the test is finished the static field _<b>innerUnitOfWork</b> of my <b>UnitOfWork</b> class is set to a value other than <b>null</b>. This will have a undesired side effect to the following test. I have to reset this field. Again in this special case I&#39;ll do it via reflection to not clutter the interface of my class (static classes are difficult more complex to deal with in TDD than non static classes...). We do reset our UnitOfWork class in the TearDownContext method</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[TearDown]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> TearDownContext()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _mocks.VerifyAll();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#008000;">// assert that the UnitOfWork is reset</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var fieldInfo = <span style="color:#0000ff;">typeof</span>(UnitOfWork).GetField(<span style="color:#006080;">&quot;_innerUnitOfWork&quot;</span>,</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> BindingFlags.Static | BindingFlags.SetField | BindingFlags.NonPublic);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> fieldInfo.SetValue(<span style="color:#0000ff;">null</span>, <span style="color:#0000ff;">null</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>Next we want to be able to access the current unit of work. As usual we first implement a test</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_access_current_unit_of_work()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> IUnitOfWork uow = UnitOfWork.Start();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var current = UnitOfWork.Current;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreSame(uow, current);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>You can figure out what code you need to implement for the test to pass.</p> <p>We also want to assert that when accessing the current UoW if no UoW has been started that a meaningful exception is thrown</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Accessing_Current_UnitOfWork_if_not_started_throws()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">try</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var current = UnitOfWork.Current;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">catch</span> (InvalidOperationException ex)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> { }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>now my implementation of the Current property in the UnitOfWork class is as follows</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> IUnitOfWork Current</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">if</span> (_innerUnitOfWork == <span style="color:#0000ff;">null</span>)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">throw</span> <span style="color:#0000ff;">new</span> InvalidOperationException(<span style="color:#006080;">&quot;You are not in a unit of work.&quot;</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> _innerUnitOfWork;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Next we want a property on the class which tells us whether a UoW is started or not. The test for it</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_test_if_UnitOfWork_Is_Started()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.IsFalse(UnitOfWork.IsStarted);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> IUnitOfWork uow = UnitOfWork.Start();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Assert.IsTrue(UnitOfWork.IsStarted);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>It&#39;s getting boring isn&#39;t it... But this is the way <b>TDD</b> works. You always think (hard) on what you need and then you implement the test with which you can proof that you get it as you want it. Only then you implement the functionality needed to fulfill the test. If you do so you automatically follow the <b>YAGNI</b> principle (you ain&#39;t gona need it) that is you only implement the code you really need!</p> <p>We can fulfill the test like so</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">bool</span> IsStarted</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get { <span style="color:#0000ff;">return</span> _innerUnitOfWork != <span style="color:#0000ff;">null</span>; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>The UnitOfWork class is now a perfect wrapper for the NHibernate session object. Though for some advance scenarios I would like to have access to the session object related to my UoW. As a consequence I&#39;ll implement a read only property CurrentSession in the UnitOfWork class. Lets again start with the test</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_get_valid_current_session_if_UoW_is_started()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">using</span> (UnitOfWork.Start())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> ISession session = UnitOfWork.CurrentSession;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Assert.IsNotNull(session);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>and the implementation</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> ISession CurrentSession</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get { <span style="color:#0000ff;">return</span> _unitOfWorkFactory.CurrentSession; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">internal</span> set { _unitOfWorkFactory.CurrentSession = <span style="color:#0000ff;">value</span>; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Note that I have just delegated the call to the factory class. Thus to make the test pass I have to add two additional lines to the SetupContext method of the test fixture where I mock a session object and setup the result for a call to the property CurrentSession of the factory.</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[SetUp]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> SetupContext()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _factory = _mocks.DynamicMock&lt;IUnitOfWorkFactory&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _unitOfWork = _mocks.DynamicMock&lt;IUnitOfWork&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _session = _mocks.DynamicMock&lt;ISession&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#008000;">// brute force attack to set my own factory via reflection</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var fieldInfo = <span style="color:#0000ff;">typeof</span>(UnitOfWork).GetField(<span style="color:#006080;">&quot;_unitOfWorkFactory&quot;</span>,</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> BindingFlags.Static | BindingFlags.SetField | BindingFlags.NonPublic);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> fieldInfo.SetValue(<span style="color:#0000ff;">null</span>, _factory);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _mocks.BackToRecordAll();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> SetupResult.For(_factory.Create()).Return(_unitOfWork);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> SetupResult.For(_factory.CurrentSession).Return(_session);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _mocks.ReplayAll();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>That&#39;s all we need for the moment regarding the UnitOfWork class. Next topics will be the the implementation of the UnitOfWorkFactory class and then of the UnitOfWorkImplementor class. The details will be presented in the next part of this article.</p> <h1>Part 2</h1> <h2>Design and Implementation</h2> <h3>The Unit Of Work Factory</h3> <p>The creation of a unit of work instance is a complex process and as such is a good candidate for a factory.</p> <p>Since a UoW (Unit of Work) is basically a wrapper around a NHibernate session object I&#39;ll need to open such a session whenever I start a new UoW. But to be able to get such a session NHibernate has to be configured and a NHibernate Session Factory has to be available. The interface of my UoW factory is defined as follows</p> <p><img src="/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/nhibernate.UoW/UoW-UoW_2D00_Factory.png" alt="" /></p> <p>I basically have two public methods on my factory. One for the creation of the UoW and the second for the disposal of a specific UoW instance. The disposal involves also some work and thus justifies the existence of this second factory method. The 3 properties <b>Configuration</b>, <b>SessionFactory</b> and <b>CurrentSession</b> are there mostly for advanced scenarios (and as such could theoretically be omitted in a first simple implementation).</p> <p>Let&#39;s now write the test for the Create method of the UoW factory implementation. At first I prepare a new test fixture class</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">using</span> System;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">using</span> NHibernate;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">using</span> NUnit.Framework;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">namespace</span> NHibernateUnitOfWork.Tests</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> [TestFixture]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> UnitOfWorkFactory_Fixture</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> IUnitOfWorkFactory _factory;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> [SetUp]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> SetupContext()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _factory = (IUnitOfWorkFactory) Activator.CreateInstance(<span style="color:#0000ff;">typeof</span> (UnitOfWorkFactory), <span style="color:#0000ff;">true</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>Why the heck do I need the <b>Activator.CreateInstance</b> to get an instance of the factory? Well I decided that the construction of a new factory instance should be internal to the assembly implementing the Unit of Work pattern. Thus the (default) constructor of the <b>UnitOfWorkFactory</b> class has a modifier <b>internal</b> and as a consequence cannot be used from code outside the assembly in which the factory is implemented. But I need an instance when testing and thus have to resort to the technique used above.</p> <p>Now the question is: &quot;what confirms me that the method Create of the factory works as expected?&quot;. I have chosen the following: I expect</p> <ul> <li>the method returning a non null instance of type <b>IUnitOfWork</b> </li> <li>the returned instance having a non null (NHibernate) <b>session</b> </li> <li>the (NHibernate) session having the Flush Mode set to <b>commit</b> (that is: the session is never flushed except when I explicitly commit a transaction - see the NHibernate <a href="http://www.hibernate.org/5.html#A25">documentation</a> for any details about the Flush Mode) </li> </ul> <p>Now the code</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_create_unit_of_work()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> IUnitOfWork implementor = _factory.Create(); </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Assert.IsNotNull(implementor);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.IsNotNull(_factory.CurrentSession);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Assert.AreEqual(FlushMode.Commit, _factory.CurrentSession.FlushMode);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>and the implementation</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> UnitOfWorkFactory : IUnitOfWorkFactory</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">static</span> ISession _currentSession;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> ISessionFactory _sessionFactory;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">internal</span> UnitOfWorkFactory()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> { }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> IUnitOfWork Create()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> ISession session = CreateSession();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> session.FlushMode = FlushMode.Commit;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _currentSession = session;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">return</span> <span style="color:#0000ff;">new</span> UnitOfWorkImplementor(<span style="color:#0000ff;">this</span>, session);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>As you can see I first need a new session instance. I then set the flush mode to commit and assign the session to an instance variable for further use. Finally I return a new instance of the <b>UnitOfWorkImplementor</b> (which implements the interface IUnitOfWork). The constructor of the <b>UnitOfWorkImplementor</b> class requires two parameters, the session and a reference to this factory.</p> <p>To be able to compile I also have to define the <b>UnitOfWorkImplementor</b> class. Of this class I just implement the minimum needed so far</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> UnitOfWorkImplementor : IUnitOfWork</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">readonly</span> IUnitOfWorkFactory _factory;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">readonly</span> ISession _session;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> UnitOfWorkImplementor(IUnitOfWorkFactory factory, ISession session)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _factory = factory;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _session = session;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Now back to the implementation of the <b>CreateSession</b> method. To be able to create (and open) a session NHibernate must have been configured previously. So I solve this problem first. </p> <p>First we add a file <b>hibernate.cfg.xml</b> to our test project and put the following content into it (don&#39;t forget to set the property &#39;Copy to Output Directory&#39; of this file to &#39;Copy always&#39;).</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">&lt;?</span><span style="color:#800000;">xml</span> <span style="color:#ff0000;">version</span><span style="color:#0000ff;">=&quot;1.0&quot;</span> <span style="color:#ff0000;">encoding</span><span style="color:#0000ff;">=&quot;utf-8&quot;</span> ?<span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">&lt;</span><span style="color:#800000;">hibernate-configuration</span> <span style="color:#ff0000;">xmlns</span><span style="color:#0000ff;">=&quot;urn:nhibernate-configuration-2.2&quot;</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">session-factory</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">property</span> <span style="color:#ff0000;">name</span><span style="color:#0000ff;">=&quot;connection.provider&quot;</span><span style="color:#0000ff;">&gt;</span>NHibernate.Connection.DriverConnectionProvider<span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">property</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">property</span> <span style="color:#ff0000;">name</span><span style="color:#0000ff;">=&quot;dialect&quot;</span><span style="color:#0000ff;">&gt;</span>NHibernate.Dialect.MsSql2005Dialect<span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">property</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">property</span> <span style="color:#ff0000;">name</span><span style="color:#0000ff;">=&quot;connection.driver_class&quot;</span><span style="color:#0000ff;">&gt;</span>NHibernate.Driver.SqlClientDriver<span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">property</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">property</span> <span style="color:#ff0000;">name</span><span style="color:#0000ff;">=&quot;connection.connection_string&quot;</span><span style="color:#0000ff;">&gt;</span>Server=(local);Database=Test;Integrated Security=SSPI;<span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">property</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">property</span> <span style="color:#ff0000;">name</span><span style="color:#0000ff;">=&quot;show_sql&quot;</span><span style="color:#0000ff;">&gt;</span>true<span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">property</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">session-factory</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">hibernate-configuration</span><span style="color:#0000ff;">&gt;</span></pre> </div> </div> <p>The above configuration file assumes that you have an <b>SQL Server 2005</b> installed on your local machine and that you are using <b>integrated security</b> to authenticate and authorize the access to the database. It further assumes that there exists a database called <b>&#39;Test&#39;</b> on this server. To configure NHibernate for other types of databases please consult the online documentation <a href="http://www.hibernate.org/361.html">here</a>.</p> <p>Now we define this test method</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_configure_NHibernate()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var configuration = _factory.Configuration;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Assert.IsNotNull(configuration);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreEqual(<span style="color:#006080;">&quot;NHibernate.Connection.DriverConnectionProvider&quot;</span>, </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> configuration.Properties[<span style="color:#006080;">&quot;connection.provider&quot;</span>]);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreEqual(<span style="color:#006080;">&quot;NHibernate.Dialect.MsSql2005Dialect&quot;</span>, </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> configuration.Properties[<span style="color:#006080;">&quot;dialect&quot;</span>]);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreEqual(<span style="color:#006080;">&quot;NHibernate.Driver.SqlClientDriver&quot;</span>, </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> configuration.Properties[<span style="color:#006080;">&quot;connection.driver_class&quot;</span>]);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreEqual(<span style="color:#006080;">&quot;Server=(local);Database=Test;Integrated Security=SSPI;&quot;</span>, </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> configuration.Properties[<span style="color:#006080;">&quot;connection.connection_string&quot;</span>]);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>Here we test whether we can successfully create a configuration and whether this configuration contains the attributes we have defined via the NHibernate configuration file.</p> <p>To fulfill this test we can e.g. implement the following code</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> Configuration Configuration</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">if</span> (_configuration == <span style="color:#0000ff;">null</span>)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _configuration = <span style="color:#0000ff;">new</span> Configuration();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">string</span> hibernateConfig = Default_HibernateConfig;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#008000;">//if not rooted, assume path from base directory</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">if</span> (Path.IsPathRooted(hibernateConfig) == <span style="color:#0000ff;">false</span>)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> hibernateConfig = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, hibernateConfig);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">if</span> (File.Exists(hibernateConfig))</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _configuration.Configure(<span style="color:#0000ff;">new</span> XmlTextReader(hibernateConfig));</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> _configuration;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Note that I have defined a class variable _<b>configuration</b> such as that I only execute the configuration logic <i>once</i> during the life time of the application. Note further that in this implementation I assume that the configuration of NHibernate is defined via the <b>hibernate.cfg.xml</b> file which must be in the same directory as the test assembly.</p> <p>As soon as I have a valid configuration I can create a NHibernate session factory. Note that this is a <b>rather expensive</b> operation (takes some time depending on the number of entities you are mapping) and thus should only be executed once during the life time of the application. The access to the NHibernate SessionFactory is <i>thread safe</i>!</p> <p>Let&#39;s write a test for the creation of the SessionFactory.</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_create_and_access_session_factory()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var sessionFactory = _factory.SessionFactory;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Assert.IsNotNull(sessionFactory);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreEqual(<span style="color:#006080;">&quot;NHibernate.Dialect.MsSql2005Dialect&quot;</span>, sessionFactory.Dialect.ToString());</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>This is a rather basic test and only checks whether I can successfully create a session factory and whether at least one of its properties is configured as I expect it, namely the dialect used.</p> <p>The implementation to fulfill the test is rather simple</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> ISessionFactory SessionFactory</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">if</span> (_sessionFactory == <span style="color:#0000ff;">null</span>)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _sessionFactory = Configuration.BuildSessionFactory();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> _sessionFactory;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>I have defined a class variable _sessionFactory such that I only execute the BuildSessionFactory method once during the life time of the application. The session factory is created on demand, that is when first needed. At the same time this property getter method accesses the previously defined Configuration property which in turn triggers the configuration of NHibernate (if not already done).</p> <p>The last missing piece is the implementation of the CreateSession method which now is trivial</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">private</span> ISession CreateSession()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> SessionFactory.OpenSession();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>I want to be able to access the current (open) session via my factory. If there is no such session open at the moment a meaningful exception should be raised. To test this write </p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Accessing_CurrentSession_when_no_session_open_throws()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">try</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var session = _factory.CurrentSession;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">catch</span> (InvalidOperationException)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> { }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>and the implementation is easy</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> ISession CurrentSession</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">if</span> (_currentSession == <span style="color:#0000ff;">null</span>)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">throw</span> <span style="color:#0000ff;">new</span> InvalidOperationException(<span style="color:#006080;">&quot;You are not in a unit of work.&quot;</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> _currentSession;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> set { _currentSession = <span style="color:#0000ff;">value</span>; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>The last method to implement is the UoW disposal method. In this method I want to reset the CurrentSession to null and then forward the call to our static UnitOfWork class (defined in the <a href="http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/04/10/nhibernate-and-the-unit-of-work-pattern.aspx">first part</a> of this post series) such as that this class can also make an internal clean-up. The implementation might look as follows</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> DisposeUnitOfWork(UnitOfWorkImplementor adapter)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> CurrentSession = <span style="color:#0000ff;">null</span>;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> UnitOfWork.DisposeUnitOfWork(adapter);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>That&#39;s all we have to do for now regarding the UoW factory. Again we have implemented it in a TDD way. When we later re-factor our implementation to make it thread-safe this TDD approach will be a huge benefit since we have a complete test coverage of out code.</p> <h3>The Unit of Work Implementor</h3> <p>This class defines an actual Unit of Work instance. It implements the already mentioned (and defined) interface IUnitOfWork which in turn inherits from IDisposal. This allows us to work with a UoW using the following syntax</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">using</span>(UnitOfWork.Start())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#008000;">// use Unit of Work</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>at the end of the block the Dispose method of the UoW will be called. So let&#39;s first think of a test for the implementation of this method. Here we have to use mocking to be able to test our SUT (system under test) in isolation. So let me setup a test fixture first.</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[TestFixture]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> UnitOfWorkImplementor_Fixture</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">readonly</span> MockRepository _mocks = <span style="color:#0000ff;">new</span> MockRepository();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">private</span> IUnitOfWorkFactory _factory;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> ISession _session;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">private</span> IUnitOfWorkImplementor _uow;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> [SetUp]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> SetupContext()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _factory = _mocks.DynamicMock&lt;IUnitOfWorkFactory&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _session = _mocks.DynamicMock&lt;ISession&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Again I use <a href="http://www.ayende.com/projects/rhino-mocks.aspx">Rhino.Mocks</a> as my mocking framework. My UoW instance has two external dependencies namely the UnitOfWork factory and the NHibernate session. In the SetupContext I generate a dynamic mock for each of them.</p> <p>Now I&nbsp; can write my test method</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_Dispose_UnitOfWorkImplementor()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">using</span>(_mocks.Record())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Expect.Call(() =&gt; _factory.DisposeUnitOfWork(<span style="color:#0000ff;">null</span>)).IgnoreArguments();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Expect.Call(_session.Dispose);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">using</span> (_mocks.Playback())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _uow = <span style="color:#0000ff;">new</span> UnitOfWorkImplementor(_factory, _session);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _uow.Dispose();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>During the recording phase I define my expectations (of what should happen when calling the <b>Dispose</b> method of the UoW). First the <b>DisposeUnitOfWork</b> method of the factory and second the <b>Dispose</b> method of the session object should be called.</p> <p>Here is the code which fulfills this test</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Dispose()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _factory.DisposeUnitOfWork(<span style="color:#0000ff;">this</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _session.Dispose();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>As you can see I just forward the call to the Unit of Work factory and dispose my internal (NHibernate) session instance as formulated in the expectations of the test.</p> <p>When working with a UoW I also have to be able to use transactions. Thus I need a way to &quot;play&quot; with transactions. Let&#39;s call the corresponding methods <b>BeginTransaction</b> and <b>TransactionalFlush</b>.</p> <h3>Generic Transaction</h3> <p>To shield the client code from all NHibernate specifics and to provide a simple(r) interface I define a <b>GenericTransaction</b> class (which implements the interface <b>IGenericTransaction</b>) which is just a wrapper around the NHibernate transaction. </p> <p>I think that the implementation is trivial and doesn&#39;t need any further explanation</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">interface</span> IGenericTransaction : IDisposable</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">void</span> Commit();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">void</span> Rollback();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> GenericTransaction : IGenericTransaction</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">readonly</span> ITransaction _transaction;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> GenericTransaction(ITransaction transaction)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _transaction = transaction;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Commit()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _transaction.Commit();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Rollback()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _transaction.Rollback();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Dispose()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _transaction.Dispose();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>just note that the <b>IGenericTransaction</b> inherits form <b>IDisposable</b>.</p> <p>With this definition of a generic transaction we can proceed to the implementation of the <b>BeginTransaction</b> and <b>TransactionalFlush</b> methods. </p> <p>First I&#39;ll implement the BeginTransaction method. As usual I define the test first</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_BeginTransaction()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">using</span>(_mocks.Record())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Expect.Call(_session.BeginTransaction()).Return(<span style="color:#0000ff;">null</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">using</span> (_mocks.Playback())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _uow = <span style="color:#0000ff;">new</span> UnitOfWorkImplementor(_factory, _session);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var transaction = _uow.BeginTransaction();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.IsNotNull(transaction);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>I expect that during execution of the method under test the BeginTransaction method of the NHibernate session is called. After calling <b>BeginTransaction</b> on the UoW (in the Playback phase) I additionally test whether I get a not-null transaction.</p> <p>I also want to be able to start a transaction and define an <a href="http://www.hibernate.org/hib_docs/nhibernate/html/transactions.html">isolation level for the transaction</a>. The corresponding test might look like</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_BeginTransaction_specifying_isolation_level()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var isolationLevel = IsolationLevel.Serializable;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">using</span>(_mocks.Record())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> { </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Expect.Call(_session.BeginTransaction(isolationLevel)).Return(<span style="color:#0000ff;">null</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">using</span> (_mocks.Playback())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _uow = <span style="color:#0000ff;">new</span> UnitOfWorkImplementor(_factory, _session);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var transaction = _uow.BeginTransaction(isolationLevel);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Assert.IsNotNull(transaction);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>To fulfill the test(s) I just have to create a new instance of a generic transaction and pass the result of the <i>_session.BeginTransaction</i> call to the constructor (that is: a NHibernate ITransaction object)</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> IGenericTransaction BeginTransaction()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> <span style="color:#0000ff;">new</span> GenericTransaction(_session.BeginTransaction());</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> IGenericTransaction BeginTransaction(IsolationLevel isolationLevel)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">return</span> <span style="color:#0000ff;">new</span> GenericTransaction(_session.BeginTransaction(isolationLevel));</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>The methods each return me an instance of type GenericTransaction which I can use in my code and call their respective commit or rollback methods if appropriate.</p> <p>The <b>TransactionalFlush</b> method should flush the content of the NHibernate session to the database wrapped inside a transaction. Let&#39;s define the test(s) for it</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_execute_TransactionalFlush()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var tx = _mocks.CreateMock&lt;ITransaction&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var session = _mocks.DynamicMock&lt;ISession&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> SetupResult.For(session.BeginTransaction(IsolationLevel.ReadCommitted)).Return(tx);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _uow = _mocks.PartialMock&lt;UnitOfWorkImplementor&gt;(_factory, _session);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">using</span> (_mocks.Record())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Expect.Call(tx.Commit);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Expect.Call(tx.Dispose);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">using</span> (_mocks.Playback())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _uow = <span style="color:#0000ff;">new</span> UnitOfWorkImplementor(_factory, session);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _uow.TransactionalFlush();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_execute_TransactionalFlush_specifying_isolation_level()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var tx = _mocks.CreateMock&lt;ITransaction&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var session = _mocks.DynamicMock&lt;ISession&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> SetupResult.For(session.BeginTransaction(IsolationLevel.Serializable)).Return(tx);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _uow = _mocks.PartialMock&lt;UnitOfWorkImplementor&gt;(_factory, session);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">using</span> (_mocks.Record())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Expect.Call(tx.Commit);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Expect.Call(tx.Dispose);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">using</span> (_mocks.Playback())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _uow.TransactionalFlush(IsolationLevel.Serializable);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>and the implementation is straight forward</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> TransactionalFlush()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> TransactionalFlush(IsolationLevel.ReadCommitted);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> TransactionalFlush(IsolationLevel isolationLevel)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> IGenericTransaction tx = BeginTransaction(isolationLevel);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">try</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#008000;">//forces a flush of the current unit of work</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> tx.Commit();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">catch</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> tx.Rollback();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">throw</span>;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">finally</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> tx.Dispose();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Note that when you don&#39;t provide an explicit transaction isolation level our implementation automatically assumes an isolation level equal to &quot;read commited&quot;. Note also that if the Commit of the transaction fails the transaction is rolled back.</p> <p><b>Important</b>: In the case of an exception during <b>TransactionalFlush</b> do not try to reuse the current unit of work since the session is in an <a href="http://www.hibernate.org/42.html#A3">inconsistent state</a> and must be closed. Thus abandon this UoW and start a new one.</p> <p>To increase the usability of the UoW instance a little bit I add the following members (which need no further explanation)</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">bool</span> IsInActiveTransaction</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> _session.Transaction.IsActive;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> IUnitOfWorkFactory Factory</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get { <span style="color:#0000ff;">return</span> _factory; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> ISession Session</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> get { <span style="color:#0000ff;">return</span> _session; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Flush()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _session.Flush();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>That&#39;s it! We have now a simple implementation of the Unit of Work pattern for NHibernate. Let me provide an overall picture of our implementation</p> <p><img src="/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/nhibernate.UoW/UoW-overview.png" alt="" /></p> <p><b>Please remember</b>: In this current version the UoW is strictly NOT thread-safe! But I&#39;ll show you how to make it thread-safe in the next post.&nbsp; </p> <h2>Using the Unit of Work</h2> <p>In the following section I&#39;ll quickly show the typical usage of the UoW. As usual I do this via TDD. I want to demonstrate how one can define a new instance of an entity and add it to the database. In this case the entity is a simple Person type object.</p> <p>Let us first set up a test fixture as follows</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">using</span> System;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">using</span> System.Reflection;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">using</span> NHibernate.Tool.hbm2ddl;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">using</span> NUnit.Framework;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">namespace</span> NHibernateUnitOfWork.Tests</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> [TestFixture]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> Test_usage_of_UnitOfWork</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> [SetUp]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> SetupContext()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> UnitOfWork.Configuration.AddAssembly(Assembly.GetExecutingAssembly());</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">new</span> SchemaExport(UnitOfWork.Configuration).Execute(<span style="color:#0000ff;">false</span>, <span style="color:#0000ff;">true</span>, <span style="color:#0000ff;">false</span>, <span style="color:#0000ff;">false</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>In the <b>SetupContext</b> method I first add the current assembly (the one in which this test is running) as a source of the <i>schema mapping information</i> to the configuration of NHibernate (which I can access via our <b>UnitOfWork</b> class). It is important that this call is done prior to the creation of the <b>SessionFactory</b> (that is prior to using a session).</p> <p>After extending the configuration I use the <b>SchemaExport</b> class of NHibernate to automatically generate the database schema for me.</p> <p>But wait: up to now I have not defined any schema at all! So let&#39;s do it now. Let&#39;s define a simple <b>Person</b> entity. Add a new file <b>Person.cs</b> to the test project and add the following code</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> Person</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">virtual</span> Guid Id { get; set; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">virtual</span> <span style="color:#0000ff;">string</span> Name { get; set; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">virtual</span> DateTime Birthdate { get; set; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>add an XML mapping document called <b>Person.hbm.xml</b> to the test project and define the following content</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">&lt;?</span><span style="color:#800000;">xml</span> <span style="color:#ff0000;">version</span><span style="color:#0000ff;">=&quot;1.0&quot;</span> <span style="color:#ff0000;">encoding</span><span style="color:#0000ff;">=&quot;utf-8&quot;</span> ?<span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">&lt;</span><span style="color:#800000;">hibernate-mapping</span> <span style="color:#ff0000;">xmlns</span><span style="color:#0000ff;">=&quot;urn:nhibernate-mapping-2.2&quot;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#ff0000;">assembly</span><span style="color:#0000ff;">=&quot;NHibernateUnitOfWork.Tests&quot;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#ff0000;">namespace</span><span style="color:#0000ff;">=&quot;NHibernateUnitOfWork.Tests&quot;</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">class</span> <span style="color:#ff0000;">name</span><span style="color:#0000ff;">=&quot;Person&quot;</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">id</span> <span style="color:#ff0000;">name</span><span style="color:#0000ff;">=&quot;Id&quot;</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">generator</span> <span style="color:#ff0000;">class</span><span style="color:#0000ff;">=&quot;guid&quot;</span><span style="color:#0000ff;">/&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">id</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">property</span> <span style="color:#ff0000;">name</span><span style="color:#0000ff;">=&quot;Name&quot;</span> <span style="color:#ff0000;">not-null</span><span style="color:#0000ff;">=&quot;true&quot;</span> <span style="color:#ff0000;">length</span><span style="color:#0000ff;">=&quot;50&quot;</span><span style="color:#0000ff;">/&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">property</span> <span style="color:#ff0000;">name</span><span style="color:#0000ff;">=&quot;Birthdate&quot;</span> <span style="color:#ff0000;">not-null</span><span style="color:#0000ff;">=&quot;true&quot;</span><span style="color:#0000ff;">/&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">class</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">hibernate-mapping</span><span style="color:#0000ff;">&gt;</span></pre> </div> </div> <p>Don&#39;t forget to set the &#39;Build Action&#39; property of this item to <b>&#39;Embedded Resource&#39;</b>!</p> <p>Now we can write a test to insert a new person instance into the database.</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_add_a_new_instance_of_an_entity_to_the_database()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">using</span>(UnitOfWork.Start())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var person = <span style="color:#0000ff;">new</span> Person {Name = <span style="color:#006080;">&quot;John Doe&quot;</span>, Birthdate = <span style="color:#0000ff;">new</span> DateTime(1915, 12, 15)};</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> UnitOfWork.CurrentSession.Save(person);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> UnitOfWork.Current.TransactionalFlush();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>When running this test the output generated by NHibernate looks similar to this</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">NHibernate: INSERT <span style="color:#0000ff;">INTO</span> Person (Name, Birthdate, Id) <span style="color:#0000ff;">VALUES</span> (@p0, @p1, @p2); </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">@p0 = <span style="color:#006080;">&#39;John Doe&#39;</span>, @p1 = <span style="color:#006080;">&#39;15.12.1915 00:00:00&#39;</span>, </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">@p2 = <span style="color:#006080;">&#39;bb72ae4c-7d64-4c16-84dc-c0ba2c7d306b&#39;</span></pre> </div> </div> <h2>Summary</h2> <p>I have shown you a possible implementation of the <b>Unit of Work</b> pattern for NHibernate. The implementation has been developed by using <a href="http://en.wikipedia.org/wiki/Test-driven_development">TDD</a>. The usage of a Unit of Work pattern simplifies the data manipulation tasks and hides the infrastructure details from the consumer of the UoW. NHibernate offers it&#39;s own implementation of the UoW in the form of the Session object. But NHibernate is just one of several possible ORM tools. With this implementation of the UoW pattern we have hidden most of the specifics of NHibernate an provide a generic interface to the consumer of the UoW.</p> <p>There are just two open points </p> <ul> <li>our implementation in <b>not</b> thread safe </li> <li>we still need to access the session object (through UnitOfWork.CurrentSession) to read or modify our entites </li> </ul> <p>The former I&#39;ll cover in the third part of this article and the latter problem can be solved by introducing a (generic) repository.</p> <h1>Part 3</h1> <h2>Introduction</h2> <p>In the previous two chapters<a href="http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/04/13/nhibernate-and-the-unit-of-work-pattern-part-2.aspx"></a> I introduced the Unit of Work pattern and developed a working version based on NHibernate. One weak point of the shown implementation is that it is strictly <i>non thread safe</i>. In NHibernate the <b>session object</b> takes the role of the Unit of Work container. The session object is not thread safe! That is a session instance may not be accessed from different threads. If your application is running on multiple threads (typically an application running on the server) then you have to open a new session instance for each running thread. </p> <p>In this post I want to improve the implementation of the Unit of Work pattern such as that it is thread safe. The class which starts a new unit of work is a static class. All static members of this class are accessible from each thread of the application domain in which your application is running. Now fortunately .NET provides us a mean to define pseudo static fields in a type which are local to a single thread. That is this state is not shared between different threads. Each thread has its own thread static state. To make a field thread static one has to decorate it with the [<b>ThreadStatic</b>] attribute. </p> <p>The easiest and most pragmatic approach would now be to just decorate our _<b>innerUnitOfWork</b> field of the <b>UnitOfWork </b>class with the [ThreadStatic] attribute. But eventually we want to keep additional state in our Unit of Work. Thus we implement a special <b>Data</b> class which is a kind of a wrapper around a Hashtable. </p> <h2>Container for Thread Static State</h2> <p>There are 2 possible scenarios I want to discuss. You either develop an application with a web client or an application with a windows client (e.g. WinForms). </p> <p>In a web application one has the so called <b>Http context</b> for each request. Multiple requests from different clients can run at the same but each of them runs on a different thread and has it&#39;s own context. In this situation we store the data relevant to the unit of work in the context of the request.</p> <p>In a windows client application (i.e. Smart Client Application) on the other hand we have a single client that might run on different threads at the same time. In this situation we &quot;attach&quot; the data relevant to the unit of work in so called thread-static fields. A thread-static field is not shared between different threads in the same application. To make a (static) field thread-static we have to just decorate it with a [<b>ThreadStatic</b>] attribute.</p> <p>In our Unit of Work implementation we have the static UnitOfWork class which contains a static field _<b>innerUnitOfWork</b> of type <b>IUnitOfWork</b>. We now need to change <i>this</i> since this kind of implementation is not thread safe. Since we might want to save other data in a thread safe way as well (not just the current instance of the unit of work) we choose a slightly more sophisticated solution.</p> <p>Let&#39;s define a static class <b>Local</b> which encapsulates the details whether we run a web- or a win-application. This class has just one (static) read-only property Data of type <b>ILocalData</b>.</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">using</span> System;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">using</span> System.Collections;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">namespace</span> NHibernateUnitOfWork</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">class</span> Local</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">readonly</span> ILocalData _data = <span style="color:#0000ff;">new</span> LocalData();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> ILocalData Data</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> get { <span style="color:#0000ff;">return</span> _data; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">class</span> LocalData : ILocalData</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#008000;">// implementation details to de defined</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>All details of our implementation are now &quot;hidden&quot; in the class <b>LocalData</b> which we choose to be a private child class of the <b>Local</b> class. We now want to be able to save into and read data from this local container via a key, e.g.</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">Local.Data[<span style="color:#006080;">&quot;some key&quot;</span>] = someValue;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#008000;">// or</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">otherValue = Local.Data[<span style="color:#006080;">&quot;other key&quot;</span>];</pre> </div> </div> <p>This should be in a thread safe way. Obviously the above sample client code implies that we use some kind of <i>dictionary</i> to internally store our data.</p> <p>As usual we formulate our intention in a unit test which might look like this</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">using</span> System;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">using</span> NUnit.Framework;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">namespace</span> NHibernateUnitOfWork.Tests</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> [TestFixture]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> LocalData_Fixture</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> [Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_store_values_in_local_data()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Local.Data[<span style="color:#006080;">&quot;one&quot;</span>] = <span style="color:#006080;">&quot;This is a string&quot;</span>;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Local.Data[<span style="color:#006080;">&quot;two&quot;</span>] = 99.9m;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var person = <span style="color:#0000ff;">new</span> Person {Name = <span style="color:#006080;">&quot;John Doe&quot;</span>, Birthdate = <span style="color:#0000ff;">new</span> DateTime(1991, 1, 15)};</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Local.Data[1] = person;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Assert.AreEqual(3, Local.Data.Count);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreEqual(<span style="color:#006080;">&quot;This is a string&quot;</span>, Local.Data[<span style="color:#006080;">&quot;one&quot;</span>]);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Assert.AreEqual(99.9m, Local.Data[<span style="color:#006080;">&quot;two&quot;</span>]);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreSame(person, Local.Data[1]);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>The test shows that I want to be able to not only store basic types but any complex type in my local data container. In this case a string, an integer and an instance of a Person class. The Person class is very basic at looks like follows</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> Person</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">virtual</span> Guid Id { get; set; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">virtual</span> <span style="color:#0000ff;">string</span> Name { get; set; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">virtual</span> DateTime Birthdate { get; set; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>Please also note that I use keys of different type (<i>string</i> and <i>int</i>). </p> <h3>Implementation for Smart Client Applications</h3> <p>Let&#39;s first assume that we want to provide a thread safe unit of work implementation for the smart client application. Then the most basic implementation to fulfill&nbsp; this test is</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">private</span> <span style="color:#0000ff;">class</span> LocalData : ILocalData</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">static</span> Hashtable _localData = new Hashtable();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">object</span> <span style="color:#0000ff;">this</span>[<span style="color:#0000ff;">object</span> key]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get { <span style="color:#0000ff;">return</span> _localData[key]; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> set { _localData[key] = <span style="color:#0000ff;">value</span>; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">int</span> Count</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get { <span style="color:#0000ff;">return</span> _localData.Count; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>I just take a hash table as local storage and define an indexer property and a Count property (Note: a <i>HashTable</i> is an often used implementation of a <i>Dictionary</i>).</p> <p>We want to also be able to <b>clear</b> the content of the local store and thus we define the following test</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_clear_local_data()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Local.Data[<span style="color:#006080;">&quot;one&quot;</span>] = <span style="color:#006080;">&quot;This is a string&quot;</span>;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Local.Data[<span style="color:#006080;">&quot;two&quot;</span>] = 99.9m;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreEqual(2, Local.Data.Count);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Local.Data.Clear();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreEqual(0, Local.Data.Count);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>The code to fulfill this test is trivial, just add the code snippet below to the <b>LocalData</b> class</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Clear()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _localData.Clear();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>Unfortunately the test still faults when run! This is because the local data storage is static and all test methods access the same container we have a &quot;side effect&quot; which we must now compensate. We can do it by just clearing the local data container before each test. Add this code to the test fixture class to compensate the side effect</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[SetUp]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> SetupContext()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Local.Data.Clear(); <span style="color:#008000;">// start side-effect free!</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Re-run all tests. They should now all pass...</p> <p>And now comes the &quot;tricky&quot; part of the implementation where we want to guarantee that our local data store is indeed <b>thread safe</b>. Let&#39;s first define a test for this scenario</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">private</span> ManualResetEvent _event;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Local_data_is_thread_local()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Console.WriteLine(<span style="color:#006080;">&quot;Starting in main thread {0}&quot;</span>, Thread.CurrentThread.ManagedThreadId);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Local.Data[<span style="color:#006080;">&quot;one&quot;</span>] = <span style="color:#006080;">&quot;This is a string&quot;</span>;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreEqual(1, Local.Data.Count);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _event = <span style="color:#0000ff;">new</span> ManualResetEvent(<span style="color:#0000ff;">false</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var backgroundThread = <span style="color:#0000ff;">new</span> Thread(RunInOtherThread);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> backgroundThread.Start();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#008000;">// give the background thread some time to do its job</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Thread.Sleep(100);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#008000;">// we still have only one entry (in this thread)</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Assert.AreEqual(1, Local.Data.Count);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Console.WriteLine(<span style="color:#006080;">&quot;Signaling background thread from main thread {0}&quot;</span>, Thread.CurrentThread.ManagedThreadId);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _event.Set();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> backgroundThread.Join();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">private</span> <span style="color:#0000ff;">void</span> RunInOtherThread()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Console.WriteLine(<span style="color:#006080;">&quot;Starting (background-) thread {0}&quot;</span>, Thread.CurrentThread.ManagedThreadId);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#008000;">// initially the local data must be empty for this NEW thread!</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreEqual(0, Local.Data.Count);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Local.Data[<span style="color:#006080;">&quot;one&quot;</span>] = <span style="color:#006080;">&quot;This is another string&quot;</span>;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreEqual(1, Local.Data.Count);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Console.WriteLine(<span style="color:#006080;">&quot;Waiting on (background-) thread {0}&quot;</span>, Thread.CurrentThread.ManagedThreadId);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _event.WaitOne();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Console.WriteLine(<span style="color:#006080;">&quot;Ending (background-) thread {0}&quot;</span>, Thread.CurrentThread.ManagedThreadId);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>In the above code I run two threads in parallel, the thread on which the test is running (let&#39;s call it the <b>main thread</b>) and an additional <b>background thread</b>. The code which is executed in the background thread is implemented in the helper method <b>RunInOtherThread</b>. To be able to synchronize the two threads I use an <b>Event</b>, in this case a <b>ManualResetEvent</b>. I have put some <i>Console.WriteLine</i> statements in the code for debugging purposes.</p> <p>In the main thread I add some data to the local data store. Then I spin up the background thread. In the background thread I first test that my (thread-) local data store is empty and then also fill in some data. With the <b>Assert</b> statements I test that we really have a thread safe behavior.</p> <p>The only change needed to make my implementation thread safe is to decorate the static field _localData with the [ThreadStatic] attribute.</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[ThreadStatic]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">private</span> <span style="color:#0000ff;">static</span> Hashtable _localData = <span style="color:#0000ff;">new</span> Hashtable();</pre> </div> </div> <p>When the test is run it should pass and produce an output similar to this</p> <p><img src="/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/nhibernate.UoW/UoW-Multi_2D00_Threading-UnitTest.png" alt="" /></p> <h3>Implementation for Web</h3> <p>As mentioned above in this scenario we want to store our local data in the context of the current HTTP request. </p> <p>First I want to provide an indicator whether I am running in web and thus I add the following to the code snippet to the <b>LocalData</b> class</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">bool</span> RunningInWeb</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get { <span style="color:#0000ff;">return</span> HttpContext.Current != <span style="color:#0000ff;">null</span>; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>Here I use the <b>HttpContext</b> class of the .NET framework (namespace <i>System.Web</i>). It&#39;s static property <b>Current</b> is equal to null if we do not run in the context of a web application.</p> <p>To abstract the details of the context (web- or smart client application) I define a private read-only property <b>LocalHashtable</b> as below</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">private</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">readonly</span> <span style="color:#0000ff;">object</span> LocalDataHashtableKey = <span style="color:#0000ff;">new</span> <span style="color:#0000ff;">object</span>();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">private</span> <span style="color:#0000ff;">static</span> Hashtable LocalHashtable</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">if</span> (!RunningInWeb)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">if</span> (_localData == <span style="color:#0000ff;">null</span>)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _localData = <span style="color:#0000ff;">new</span> Hashtable();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> _localData;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">else</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var web_hashtable = HttpContext.Current.Items[LocalDataHashtableKey] <span style="color:#0000ff;">as</span> Hashtable;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">if</span> (web_hashtable == <span style="color:#0000ff;">null</span>)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> web_hashtable = <span style="color:#0000ff;">new</span> Hashtable();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> HttpContext.Current.Items[LocalDataHashtableKey] = web_hashtable;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> web_hashtable;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>In this code I use the <b>RunningInWeb</b> helper method to distinguish the two cases. In the case of NOT running in web context I test whether my thread static _<b>localData</b> field is equal to null, and If so I initialize it with a new instance of type <b>Hashtable</b>. I then return this instance. On the other hand, when running in web context I try to access a hash table instance in the <b>Items</b> collection of the current Http context. If I do not find such an instance then I create a new one and put it into the items collection of the current context. I then return the instance.</p> <p>Now I have to locate every place in the <b>LocalData</b> class where I access the _<b>localData</b> field directly and replace it with a reference to the <b>LocalHashtable</b> property. E.g. the indexer will have to be changed as follows</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">object</span> <span style="color:#0000ff;">this</span>[<span style="color:#0000ff;">object</span> key]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get { <span style="color:#0000ff;">return</span> LocalHashtable[key]; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> set { LocalHashtable[key] = <span style="color:#0000ff;">value</span>; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Our thread- and/or Http context local data store is now complete and we can use it in our <b>UnitOfWork</b> class.</p> <h2>Make Unit Of Work implementation thread safe</h2> <p>To make our unit of work implementation thread safe we change the implementation of our static <b>UnitOfWork</b> class as shown below</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">class</span> UnitOfWork</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">readonly</span> IUnitOfWorkFactory _unitOfWorkFactory = <span style="color:#0000ff;">new</span> UnitOfWorkFactory();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> Configuration Configuration</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get { <span style="color:#0000ff;">return</span> _unitOfWorkFactory.Configuration; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">const</span> <span style="color:#0000ff;">string</span> CurrentUnitOfWorkKey = <span style="color:#006080;">&quot;CurrentUnitOfWork.Key&quot;</span>;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">static</span> IUnitOfWork CurrentUnitOfWork</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> get { <span style="color:#0000ff;">return</span> Local.Data[CurrentUnitOfWorkKey] <span style="color:#0000ff;">as</span> IUnitOfWork; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> set { Local.Data[CurrentUnitOfWorkKey] = <span style="color:#0000ff;">value</span>; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> IUnitOfWork Current</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> get</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var unitOfWork = CurrentUnitOfWork;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">if</span> (unitOfWork == <span style="color:#0000ff;">null</span>)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">throw</span> <span style="color:#0000ff;">new</span> InvalidOperationException(<span style="color:#006080;">&quot;You are not in a unit of work&quot;</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> unitOfWork;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">bool</span> IsStarted</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get { <span style="color:#0000ff;">return</span> CurrentUnitOfWork != <span style="color:#0000ff;">null</span>; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> ISession CurrentSession</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> get { <span style="color:#0000ff;">return</span> _unitOfWorkFactory.CurrentSession; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">internal</span> set { _unitOfWorkFactory.CurrentSession = <span style="color:#0000ff;">value</span>; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> IUnitOfWork Start()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">if</span> (CurrentUnitOfWork != <span style="color:#0000ff;">null</span>)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">throw</span> <span style="color:#0000ff;">new</span> InvalidOperationException(<span style="color:#006080;">&quot;You cannot start more than one unit of work at the same time.&quot;</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var unitOfWork = _unitOfWorkFactory.Create();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> CurrentUnitOfWork = unitOfWork;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> unitOfWork;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">void</span> DisposeUnitOfWork(IUnitOfWorkImplementor unitOfWork)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> CurrentUnitOfWork = <span style="color:#0000ff;">null</span>;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>As you can see the field _<b>innerUnitOfWork</b> has gone and is replaced by a private property <b>CurrentUnitOfWork</b>. This property in turn uses the previously defined <b>Local </b>class to store the current unit of work item. </p> <p>Note that there is one place in our unit tests that makes a reference to the field _<b>innerUnitOfWork</b> and must thus be changed. It&#39;s the method <b>ResetUnitOfWork</b> in the class <b>UnitOfWork_With_Factory_Fixture</b>. The new implementation is</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">private</span> <span style="color:#0000ff;">void</span> ResetUnitOfWork()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#008000;">// assert that the UnitOfWork is reset</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var propertyInfo = <span style="color:#0000ff;">typeof</span>(UnitOfWork).GetProperty(<span style="color:#006080;">&quot;CurrentUnitOfWork&quot;</span>,</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> BindingFlags.Static | BindingFlags.SetProperty | BindingFlags.NonPublic);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> propertyInfo.SetValue(<span style="color:#0000ff;">null</span>, <span style="color:#0000ff;">null</span>, <span style="color:#0000ff;">null</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>When run, all tests should again pass. So now our implementation of the unit of work is thread safe.</p> <p>You can find the full code <a href="http://hibernatingrhinos.googlecode.com/svn/trunk/UnitOfWork/">here</a>.</p> <p>&nbsp;</p> <p>&nbsp;</p>NHibernate and the Unit of Work Patternhttp://nhforge.org/wikis/patternsandpractices/nhibernate-and-the-unit-of-work-pattern/revision/2.aspxTue, 23 Sep 2008 20:02:26 GMT45f813f2-f1c4-4eda-a619-288e3cadc793:153gabriel.schenkerhttp://nhforge.org/wikis/patternsandpractices/nhibernate-and-the-unit-of-work-pattern/comments.aspx<h2>Introduction</h2> <p>Martin Fowler <a href="http://martinfowler.com/eaaCatalog/unitOfWork.html">writes</a>: </p> <p>&quot;When you&#39;re pulling data in and out of a database, it&#39;s important to keep track of what you&#39;ve changed; otherwise, that data won&#39;t be written back into the database. Similarly you have to insert new objects you create and remove any objects you delete.&quot;</p> <p>and</p> <p>&quot;A <b>Unit of Work</b> keeps track of everything you do during a <i>business transaction</i> that can affect the database. When you&#39;re done, it figures out everything that needs to be done to alter the database as a result of your work.&quot;</p> <p>In NHibernate we have the <b>Session</b> object which is a Unit of Work (UoW) container. The session object keeps track of all objects you load, new objects you add, existing objects you delete and changes you make to any of these objects. Only when <b>flushing</b> the session will the database be altered (that is: will the necessary create, update and delete statements be sent to the database).</p> <p>Now, working directly with the NHibernate session object makes absolute sense. But some times you rather want to abstract the data manipulation interface from a specific infrastructure implementation &agrave; la NHibernate.</p> <p><b>Note</b>: most of the design ideas and implementation details presented here originate from <a href="http://www.ayende.com/">Ayende</a>&#39;s UnitOfWork implemented in the <b>Rhino.Commons</b> which you can get <a href="http://rhino-tools.svn.sourceforge.net/svnroot/rhino-tools/trunk">here</a>.</p> <h2>Design and Implementation (TDD)</h2> <h3>Some thought about TDD</h3> <p>I want to implement a UnitOfWork pattern for NHibernate and I want to do it by using <a href="http://en.wikipedia.org/wiki/Test-driven_development">TDD</a>. For a beginner (like I was myself not so long ago) it seems unnatural at the beginning. We introduce a huge overhead you might think. You might also think that we have to write at least double the code as when doing the development without TDD. But wait until you have to start to debug your application... or until the customer wants to have something changed in the application... or until you have to re-factor you application... Then you will immediately see and feel the benefits of a good test coverage.</p> <h3>Attention: Multi-Threading ahead</h3> <p>Please not that the implementation presented here is strictly <b>NOT</b> thread safe!!! I want to reduce the complexity of this first implementation. But <b>I promise</b> that in a following post I&#39;ll show you how to make the implementation of the unit of work pattern thread safe and thus useful for e.g. Web scenarios.</p> <h3>The UnitOfWork Class</h3> <p>To start with: I want to have an easy way to <b>start</b> a new UoW, in any place of my application have access to the <b>current</b> UoW and <b>commit</b> the <i>business transaction</i> represented by my UoW. We can do this with a static class called UnitOfWork</p> <p><a><img src="/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/nhibernate.UoW/UoW-UoW_2D00_class.png" alt="" /><br /></a></p> <p>The method start creates and returns an instance of a <b>UnitOfWorkImplementor</b> class which implements the interface <b>IUnitOfWork</b>. As you can see then interface IUnitOfWork inherits from IDisposable. So we can define that the <i>business transaction</i> is ended when the UoW is disposed. Now, if we do nothing else then nothing should happen, that is no changes should be propagated to the database. To commit a <i>business transaction</i> we have to explicitly call a method of the UoW. Let&#39;s call this method <b>TransactionalFlush</b>. In doing so all changes recorded by the UoW are committed to the database in one go.</p> <p>Now let&#39;s start to implement this! We are doing TDD, aren&#39;t we? So we will write our first test (if you are not sure how to best setup a new solution for TDD please consult <a href="http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/04/06/how-to-setup-a-new-solution.aspx">this</a> post). I define a new solution with two projects as follows</p> <p><a><img src="/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/nhibernate.UoW/UoW-Solution.png" alt="" /><br /></a></p> <p>Add a class UnitOfWork_Fixture.cs to the test project and implement the first test like this</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[TestFixture]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> UnitOfWork_Fixture</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">readonly</span> MockRepository _mocks = <span style="color:#0000ff;">new</span> MockRepository();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> [Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_Start_UnitOfWork()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> IUnitOfWork uow = UnitOfWork.Start();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Of course this test will not compile since you don&#39;t have the types UnitOfWork and IUnitOfWork defined yet. Let <a href="http://www.jetbrains.com/resharper/">Resharper</a> create them for you (or implement them by hand)</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">class</span> UnitOfWork</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> IUnitOfWork Start()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">throw</span> <span style="color:#0000ff;">new</span> NotImplementedException();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> IUnitOfWork Current { get; <span style="color:#0000ff;">private</span> set; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">interface</span> IUnitOfWork : IDisposable</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Now the test will compile but it will fail! Of course, you haven&#39;t implemented the Start method so far. In this method we must now create a new UoW and return it to the caller. A UoW is a complex beast and should therefore be constructed in a factory. So let&#39;s define a factory Interface IUnitOfWorkFactory with a method Create which returns a UoW implementing the interface IUnitOfWork.</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">interface</span> IUnitOfWorkFactory</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> IUnitOfWork Create();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>since we want to test our UnitOfWork class in isolation we have to mock all other dependencies line the unit of work factory. I&#39;ll use <b>Rhino.Mocks</b> as my mocking framework (Please refer to documentation <a href="http://www.ayende.com/wiki/Rhino+Mocks+Documentation.ashx">here</a>). I want to test that when calling the start method of the UnitOfWork class the factory gets called. So I extend my test function</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_Start_UnitOfWork()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var factory = _mocks.DynamicMock&lt;IUnitOfWorkFactory&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var unitOfWork = _mocks.DynamicMock&lt;IUnitOfWork&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#008000;">// brute force attack to set my own factory via reflection</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var fieldInfo = <span style="color:#0000ff;">typeof</span>(UnitOfWork).GetField(<span style="color:#006080;">&quot;_unitOfWorkFactory&quot;</span>, </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> BindingFlags.Static | BindingFlags.SetField | BindingFlags.NonPublic);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> fieldInfo.SetValue(<span style="color:#0000ff;">null</span>, factory);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">using</span>(_mocks.Record())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Expect.Call(factory.Create()).Return(unitOfWork);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">using</span>(_mocks.Playback())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var uow = UnitOfWork.Start();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>In the first two lines of code I mock the external dependencies of the UnitOfWork class. Then I do something you should not do very often (but I have good reasons doing so here and I promise it&#39;s the only time I&#39;ll do it in this project...). I set a private field of the UnitOfWork class with a value by using reflection. I could implement a public setter in the class but as I would only need it for this test and I want to keep the class interface as simple as possible I chose to do it via reflection.</p> <p>In the&nbsp; record phase I define my expectation (namely that the factory create method is called) and in the playback phase I invoke the Start method which I want to test. The test will compile but fail to execute. I have not yet defined the private static field _unitOfWorkFactory and I also do not call the factory. So let&#39;s modify our code...</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">class</span> UnitOfWork</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">static</span> IUnitOfWorkFactory _unitOfWorkFactory;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">static</span> IUnitOfWork _innerUnitOfWork;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> IUnitOfWork Start()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _innerUnitOfWork = _unitOfWorkFactory.Create();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> _innerUnitOfWork;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> IUnitOfWork Current { get; <span style="color:#0000ff;">private</span> set; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>now the test will pass.</p> <p>Since in all our test regarding the UnitOfWork class we will always need it with an injected factory we define a new test fixture with a context setup for our specific needs. We put the respective code in the <b>SetupContext</b> and <b>TearDownContext</b> methods</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[TestFixture]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> UnitOfWork_With_Factory_Fixture</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">readonly</span> MockRepository _mocks = <span style="color:#0000ff;">new</span> MockRepository();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">private</span> IUnitOfWorkFactory _factory;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> IUnitOfWork _unitOfWork;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> [SetUp]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> SetupContext()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _factory = _mocks.DynamicMock&lt;IUnitOfWorkFactory&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _unitOfWork = _mocks.DynamicMock&lt;IUnitOfWork&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#008000;">// brute force attack to set my own factory via reflection</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var fieldInfo = <span style="color:#0000ff;">typeof</span>(UnitOfWork).GetField(<span style="color:#006080;">&quot;_unitOfWorkFactory&quot;</span>,</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> BindingFlags.Static | BindingFlags.SetField | BindingFlags.NonPublic);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> fieldInfo.SetValue(<span style="color:#0000ff;">null</span>, _factory);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _mocks.BackToRecordAll();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> SetupResult.For(_factory.Create()).Return(_unitOfWork);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _mocks.ReplayAll();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> [TearDown]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> TearDownContext()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _mocks.VerifyAll();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p><b>Note</b>: in the second last line of the <b>SetupContext</b> method we define that each time the method Create of the factory object is called (by the UnitOfWork Start method) we want it to return our predefined mocked _<b>unitOfWork</b> instance.</p> <p>Trying to start a UoW if there is already one active should throw a meaningful exception. This is the test</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Starting_UnitOfWork_if_already_started_throws()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> UnitOfWork.Start();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">try</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> UnitOfWork.Start();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">catch</span> (InvalidOperationException ex)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> { }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>As a consequence we have to extend our Start method in the UnitOfWork class</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> IUnitOfWork Start()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">if</span> (_innerUnitOfWork != <span style="color:#0000ff;">null</span>)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">throw</span> <span style="color:#0000ff;">new</span> InvalidOperationException(<span style="color:#006080;">&quot;You cannot start more than one unit of work at the same time.&quot;</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _innerUnitOfWork = _unitOfWorkFactory.Create();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> _innerUnitOfWork;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>Now I have another problem: After the test is finished the static field _<b>innerUnitOfWork</b> of my <b>UnitOfWork</b> class is set to a value other than <b>null</b>. This will have a undesired side effect to the following test. I have to reset this field. Again in this special case I&#39;ll do it via reflection to not clutter the interface of my class (static classes are difficult more complex to deal with in TDD than non static classes...). We do reset our UnitOfWork class in the TearDownContext method</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[TearDown]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> TearDownContext()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _mocks.VerifyAll();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#008000;">// assert that the UnitOfWork is reset</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var fieldInfo = <span style="color:#0000ff;">typeof</span>(UnitOfWork).GetField(<span style="color:#006080;">&quot;_innerUnitOfWork&quot;</span>,</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> BindingFlags.Static | BindingFlags.SetField | BindingFlags.NonPublic);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> fieldInfo.SetValue(<span style="color:#0000ff;">null</span>, <span style="color:#0000ff;">null</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>Next we want to be able to access the current unit of work. As usual we first implement a test</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_access_current_unit_of_work()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> IUnitOfWork uow = UnitOfWork.Start();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var current = UnitOfWork.Current;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreSame(uow, current);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>You can figure out what code you need to implement for the test to pass.</p> <p>We also want to assert that when accessing the current UoW if no UoW has been started that a meaningful exception is thrown</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Accessing_Current_UnitOfWork_if_not_started_throws()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">try</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var current = UnitOfWork.Current;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">catch</span> (InvalidOperationException ex)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> { }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>now my implementation of the Current property in the UnitOfWork class is as follows</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> IUnitOfWork Current</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">if</span> (_innerUnitOfWork == <span style="color:#0000ff;">null</span>)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">throw</span> <span style="color:#0000ff;">new</span> InvalidOperationException(<span style="color:#006080;">&quot;You are not in a unit of work.&quot;</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> _innerUnitOfWork;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Next we want a property on the class which tells us whether a UoW is started or not. The test for it</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_test_if_UnitOfWork_Is_Started()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.IsFalse(UnitOfWork.IsStarted);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> IUnitOfWork uow = UnitOfWork.Start();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Assert.IsTrue(UnitOfWork.IsStarted);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>It&#39;s getting boring isn&#39;t it... But this is the way <b>TDD</b> works. You always think (hard) on what you need and then you implement the test with which you can proof that you get it as you want it. Only then you implement the functionality needed to fulfill the test. If you do so you automatically follow the <b>YAGNI</b> principle (you ain&#39;t gona need it) that is you only implement the code you really need!</p> <p>We can fulfill the test like so</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">bool</span> IsStarted</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get { <span style="color:#0000ff;">return</span> _innerUnitOfWork != <span style="color:#0000ff;">null</span>; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>The UnitOfWork class is now a perfect wrapper for the NHibernate session object. Though for some advance scenarios I would like to have access to the session object related to my UoW. As a consequence I&#39;ll implement a read only property CurrentSession in the UnitOfWork class. Lets again start with the test</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_get_valid_current_session_if_UoW_is_started()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">using</span> (UnitOfWork.Start())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> ISession session = UnitOfWork.CurrentSession;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Assert.IsNotNull(session);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>and the implementation</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> ISession CurrentSession</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get { <span style="color:#0000ff;">return</span> _unitOfWorkFactory.CurrentSession; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">internal</span> set { _unitOfWorkFactory.CurrentSession = <span style="color:#0000ff;">value</span>; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Note that I have just delegated the call to the factory class. Thus to make the test pass I have to add two additional lines to the SetupContext method of the test fixture where I mock a session object and setup the result for a call to the property CurrentSession of the factory.</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[SetUp]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> SetupContext()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _factory = _mocks.DynamicMock&lt;IUnitOfWorkFactory&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _unitOfWork = _mocks.DynamicMock&lt;IUnitOfWork&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _session = _mocks.DynamicMock&lt;ISession&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#008000;">// brute force attack to set my own factory via reflection</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var fieldInfo = <span style="color:#0000ff;">typeof</span>(UnitOfWork).GetField(<span style="color:#006080;">&quot;_unitOfWorkFactory&quot;</span>,</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> BindingFlags.Static | BindingFlags.SetField | BindingFlags.NonPublic);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> fieldInfo.SetValue(<span style="color:#0000ff;">null</span>, _factory);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _mocks.BackToRecordAll();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> SetupResult.For(_factory.Create()).Return(_unitOfWork);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> SetupResult.For(_factory.CurrentSession).Return(_session);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _mocks.ReplayAll();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>That&#39;s all we need for the moment regarding the UnitOfWork class. Next topics will be the the implementation of the UnitOfWorkFactory class and then of the UnitOfWorkImplementor class. The details will be presented in the next post to this blog. So keep ready...</p> <p>&nbsp;</p> <h1>Part 2</h1> <h2>Design and Implementation</h2> <h3>The Unit Of Work Factory</h3> <p>The creation of a unit of work instance is a complex process and as such is a good candidate for a factory.</p> <p>Since a UoW (Unit of Work) is basically a wrapper around a NHibernate session object I&#39;ll need to open such a session whenever I start a new UoW. But to be able to get such a session NHibernate has to be configured and a NHibernate Session Factory has to be available. The interface of my UoW factory is defined as follows</p> <p><img src="/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/nhibernate.UoW/UoW-UoW_2D00_Factory.png" alt="" /></p> <p>I basically have two public methods on my factory. One for the creation of the UoW and the second for the disposal of a specific UoW instance. The disposal involves also some work and thus justifies the existence of this second factory method. The 3 properties <b>Configuration</b>, <b>SessionFactory</b> and <b>CurrentSession</b> are there mostly for advanced scenarios (and as such could theoretically be omitted in a first simple implementation).</p> <p>Let&#39;s now write the test for the Create method of the UoW factory implementation. At first I prepare a new test fixture class</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">using</span> System;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">using</span> NHibernate;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">using</span> NUnit.Framework;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">namespace</span> NHibernateUnitOfWork.Tests</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> [TestFixture]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> UnitOfWorkFactory_Fixture</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> IUnitOfWorkFactory _factory;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> [SetUp]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> SetupContext()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _factory = (IUnitOfWorkFactory) Activator.CreateInstance(<span style="color:#0000ff;">typeof</span> (UnitOfWorkFactory), <span style="color:#0000ff;">true</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>Why the heck do I need the <b>Activator.CreateInstance</b> to get an instance of the factory? Well I decided that the construction of a new factory instance should be internal to the assembly implementing the Unit of Work pattern. Thus the (default) constructor of the <b>UnitOfWorkFactory</b> class has a modifier <b>internal</b> and as a consequence cannot be used from code outside the assembly in which the factory is implemented. But I need an instance when testing and thus have to resort to the technique used above.</p> <p>Now the question is: &quot;what confirms me that the method Create of the factory works as expected?&quot;. I have chosen the following: I expect</p> <ul> <li>the method returning a non null instance of type <b>IUnitOfWork</b> </li> <li>the returned instance having a non null (NHibernate) <b>session</b> </li> <li>the (NHibernate) session having the Flush Mode set to <b>commit</b> (that is: the session is never flushed except when I explicitly commit a transaction - see the NHibernate <a href="http://www.hibernate.org/5.html#A25">documentation</a> for any details about the Flush Mode) </li> </ul> <p>Now the code</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_create_unit_of_work()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> IUnitOfWork implementor = _factory.Create(); </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Assert.IsNotNull(implementor);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.IsNotNull(_factory.CurrentSession);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Assert.AreEqual(FlushMode.Commit, _factory.CurrentSession.FlushMode);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>and the implementation</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> UnitOfWorkFactory : IUnitOfWorkFactory</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">static</span> ISession _currentSession;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> ISessionFactory _sessionFactory;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">internal</span> UnitOfWorkFactory()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> { }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> IUnitOfWork Create()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> ISession session = CreateSession();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> session.FlushMode = FlushMode.Commit;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _currentSession = session;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">return</span> <span style="color:#0000ff;">new</span> UnitOfWorkImplementor(<span style="color:#0000ff;">this</span>, session);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>As you can see I first need a new session instance. I then set the flush mode to commit and assign the session to an instance variable for further use. Finally I return a new instance of the <b>UnitOfWorkImplementor</b> (which implements the interface IUnitOfWork). The constructor of the <b>UnitOfWorkImplementor</b> class requires two parameters, the session and a reference to this factory.</p> <p>To be able to compile I also have to define the <b>UnitOfWorkImplementor</b> class. Of this class I just implement the minimum needed so far</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> UnitOfWorkImplementor : IUnitOfWork</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">readonly</span> IUnitOfWorkFactory _factory;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">readonly</span> ISession _session;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> UnitOfWorkImplementor(IUnitOfWorkFactory factory, ISession session)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _factory = factory;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _session = session;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Now back to the implementation of the <b>CreateSession</b> method. To be able to create (and open) a session NHibernate must have been configured previously. So I solve this problem first. </p> <p>First we add a file <b>hibernate.cfg.xml</b> to our test project and put the following content into it (don&#39;t forget to set the property &#39;Copy to Output Directory&#39; of this file to &#39;Copy always&#39;).</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">&lt;?</span><span style="color:#800000;">xml</span> <span style="color:#ff0000;">version</span><span style="color:#0000ff;">=&quot;1.0&quot;</span> <span style="color:#ff0000;">encoding</span><span style="color:#0000ff;">=&quot;utf-8&quot;</span> ?<span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">&lt;</span><span style="color:#800000;">hibernate-configuration</span> <span style="color:#ff0000;">xmlns</span><span style="color:#0000ff;">=&quot;urn:nhibernate-configuration-2.2&quot;</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">session-factory</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">property</span> <span style="color:#ff0000;">name</span><span style="color:#0000ff;">=&quot;connection.provider&quot;</span><span style="color:#0000ff;">&gt;</span>NHibernate.Connection.DriverConnectionProvider<span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">property</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">property</span> <span style="color:#ff0000;">name</span><span style="color:#0000ff;">=&quot;dialect&quot;</span><span style="color:#0000ff;">&gt;</span>NHibernate.Dialect.MsSql2005Dialect<span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">property</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">property</span> <span style="color:#ff0000;">name</span><span style="color:#0000ff;">=&quot;connection.driver_class&quot;</span><span style="color:#0000ff;">&gt;</span>NHibernate.Driver.SqlClientDriver<span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">property</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">property</span> <span style="color:#ff0000;">name</span><span style="color:#0000ff;">=&quot;connection.connection_string&quot;</span><span style="color:#0000ff;">&gt;</span>Server=(local);Database=Test;Integrated Security=SSPI;<span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">property</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">property</span> <span style="color:#ff0000;">name</span><span style="color:#0000ff;">=&quot;show_sql&quot;</span><span style="color:#0000ff;">&gt;</span>true<span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">property</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">session-factory</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">hibernate-configuration</span><span style="color:#0000ff;">&gt;</span></pre> </div> </div> <p>The above configuration file assumes that you have an <b>SQL Server 2005</b> installed on your local machine and that you are using <b>integrated security</b> to authenticate and authorize the access to the database. It further assumes that there exists a database called <b>&#39;Test&#39;</b> on this server. To configure NHibernate for other types of databases please consult the online documentation <a href="http://www.hibernate.org/361.html">here</a>.</p> <p>Now we define this test method</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_configure_NHibernate()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var configuration = _factory.Configuration;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Assert.IsNotNull(configuration);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreEqual(<span style="color:#006080;">&quot;NHibernate.Connection.DriverConnectionProvider&quot;</span>, </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> configuration.Properties[<span style="color:#006080;">&quot;connection.provider&quot;</span>]);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreEqual(<span style="color:#006080;">&quot;NHibernate.Dialect.MsSql2005Dialect&quot;</span>, </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> configuration.Properties[<span style="color:#006080;">&quot;dialect&quot;</span>]);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreEqual(<span style="color:#006080;">&quot;NHibernate.Driver.SqlClientDriver&quot;</span>, </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> configuration.Properties[<span style="color:#006080;">&quot;connection.driver_class&quot;</span>]);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreEqual(<span style="color:#006080;">&quot;Server=(local);Database=Test;Integrated Security=SSPI;&quot;</span>, </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> configuration.Properties[<span style="color:#006080;">&quot;connection.connection_string&quot;</span>]);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>Here we test whether we can successfully create a configuration and whether this configuration contains the attributes we have defined via the NHibernate configuration file.</p> <p>To fulfill this test we can e.g. implement the following code</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> Configuration Configuration</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">if</span> (_configuration == <span style="color:#0000ff;">null</span>)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _configuration = <span style="color:#0000ff;">new</span> Configuration();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">string</span> hibernateConfig = Default_HibernateConfig;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#008000;">//if not rooted, assume path from base directory</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">if</span> (Path.IsPathRooted(hibernateConfig) == <span style="color:#0000ff;">false</span>)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> hibernateConfig = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, hibernateConfig);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">if</span> (File.Exists(hibernateConfig))</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _configuration.Configure(<span style="color:#0000ff;">new</span> XmlTextReader(hibernateConfig));</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> _configuration;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Note that I have defined a class variable _<b>configuration</b> such as that I only execute the configuration logic <i>once</i> during the life time of the application. Note further that in this implementation I assume that the configuration of NHibernate is defined via the <b>hibernate.cfg.xml</b> file which must be in the same directory as the test assembly.</p> <p>As soon as I have a valid configuration I can create a NHibernate session factory. Note that this is a <b>rather expensive</b> operation (takes some time depending on the number of entities you are mapping) and thus should only be executed once during the life time of the application. The access to the NHibernate SessionFactory is <i>thread safe</i>!</p> <p>Let&#39;s write a test for the creation of the SessionFactory.</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_create_and_access_session_factory()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var sessionFactory = _factory.SessionFactory;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Assert.IsNotNull(sessionFactory);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreEqual(<span style="color:#006080;">&quot;NHibernate.Dialect.MsSql2005Dialect&quot;</span>, sessionFactory.Dialect.ToString());</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>This is a rather basic test and only checks whether I can successfully create a session factory and whether at least one of its properties is configured as I expect it, namely the dialect used.</p> <p>The implementation to fulfill the test is rather simple</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> ISessionFactory SessionFactory</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">if</span> (_sessionFactory == <span style="color:#0000ff;">null</span>)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _sessionFactory = Configuration.BuildSessionFactory();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> _sessionFactory;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>I have defined a class variable _sessionFactory such that I only execute the BuildSessionFactory method once during the life time of the application. The session factory is created on demand, that is when first needed. At the same time this property getter method accesses the previously defined Configuration property which in turn triggers the configuration of NHibernate (if not already done).</p> <p>The last missing piece is the implementation of the CreateSession method which now is trivial</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">private</span> ISession CreateSession()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> SessionFactory.OpenSession();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>I want to be able to access the current (open) session via my factory. If there is no such session open at the moment a meaningful exception should be raised. To test this write </p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Accessing_CurrentSession_when_no_session_open_throws()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">try</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var session = _factory.CurrentSession;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">catch</span> (InvalidOperationException)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> { }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>and the implementation is easy</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> ISession CurrentSession</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">if</span> (_currentSession == <span style="color:#0000ff;">null</span>)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">throw</span> <span style="color:#0000ff;">new</span> InvalidOperationException(<span style="color:#006080;">&quot;You are not in a unit of work.&quot;</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> _currentSession;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> set { _currentSession = <span style="color:#0000ff;">value</span>; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>The last method to implement is the UoW disposal method. In this method I want to reset the CurrentSession to null and then forward the call to our static UnitOfWork class (defined in the <a href="http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/04/10/nhibernate-and-the-unit-of-work-pattern.aspx">first part</a> of this post series) such as that this class can also make an internal clean-up. The implementation might look as follows</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> DisposeUnitOfWork(UnitOfWorkImplementor adapter)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> CurrentSession = <span style="color:#0000ff;">null</span>;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> UnitOfWork.DisposeUnitOfWork(adapter);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>That&#39;s all we have to do for now regarding the UoW factory. Again we have implemented it in a TDD way. When we later re-factor our implementation to make it thread-safe this TDD approach will be a huge benefit since we have a complete test coverage of out code.</p> <h3>The Unit of Work Implementor</h3> <p>This class defines an actual Unit of Work instance. It implements the already mentioned (and defined) interface IUnitOfWork which in turn inherits from IDisposal. This allows us to work with a UoW using the following syntax</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">using</span>(UnitOfWork.Start())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#008000;">// use Unit of Work</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>at the end of the block the Dispose method of the UoW will be called. So let&#39;s first think of a test for the implementation of this method. Here we have to use mocking to be able to test our SUT (system under test) in isolation. So let me setup a test fixture first.</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[TestFixture]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> UnitOfWorkImplementor_Fixture</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">readonly</span> MockRepository _mocks = <span style="color:#0000ff;">new</span> MockRepository();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">private</span> IUnitOfWorkFactory _factory;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> ISession _session;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">private</span> IUnitOfWorkImplementor _uow;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> [SetUp]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> SetupContext()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _factory = _mocks.DynamicMock&lt;IUnitOfWorkFactory&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _session = _mocks.DynamicMock&lt;ISession&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Again I use <a href="http://www.ayende.com/projects/rhino-mocks.aspx">Rhino.Mocks</a> as my mocking framework. My UoW instance has two external dependencies namely the UnitOfWork factory and the NHibernate session. In the SetupContext I generate a dynamic mock for each of them.</p> <p>Now I&nbsp; can write my test method</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_Dispose_UnitOfWorkImplementor()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">using</span>(_mocks.Record())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Expect.Call(() =&gt; _factory.DisposeUnitOfWork(<span style="color:#0000ff;">null</span>)).IgnoreArguments();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Expect.Call(_session.Dispose);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">using</span> (_mocks.Playback())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _uow = <span style="color:#0000ff;">new</span> UnitOfWorkImplementor(_factory, _session);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _uow.Dispose();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>During the recording phase I define my expectations (of what should happen when calling the <b>Dispose</b> method of the UoW). First the <b>DisposeUnitOfWork</b> method of the factory and second the <b>Dispose</b> method of the session object should be called.</p> <p>Here is the code which fulfills this test</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Dispose()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _factory.DisposeUnitOfWork(<span style="color:#0000ff;">this</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _session.Dispose();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>As you can see I just forward the call to the Unit of Work factory and dispose my internal (NHibernate) session instance as formulated in the expectations of the test.</p> <p>When working with a UoW I also have to be able to use transactions. Thus I need a way to &quot;play&quot; with transactions. Let&#39;s call the corresponding methods <b>BeginTransaction</b> and <b>TransactionalFlush</b>.</p> <h3>Generic Transaction</h3> <p>To shield the client code from all NHibernate specifics and to provide a simple(r) interface I define a <b>GenericTransaction</b> class (which implements the interface <b>IGenericTransaction</b>) which is just a wrapper around the NHibernate transaction. </p> <p>I think that the implementation is trivial and doesn&#39;t need any further explanation</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">interface</span> IGenericTransaction : IDisposable</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">void</span> Commit();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">void</span> Rollback();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> GenericTransaction : IGenericTransaction</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">readonly</span> ITransaction _transaction;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> GenericTransaction(ITransaction transaction)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _transaction = transaction;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Commit()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _transaction.Commit();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Rollback()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _transaction.Rollback();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Dispose()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _transaction.Dispose();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>just note that the <b>IGenericTransaction</b> inherits form <b>IDisposable</b>.</p> <p>With this definition of a generic transaction we can proceed to the implementation of the <b>BeginTransaction</b> and <b>TransactionalFlush</b> methods. </p> <p>First I&#39;ll implement the BeginTransaction method. As usual I define the test first</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_BeginTransaction()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">using</span>(_mocks.Record())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Expect.Call(_session.BeginTransaction()).Return(<span style="color:#0000ff;">null</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">using</span> (_mocks.Playback())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _uow = <span style="color:#0000ff;">new</span> UnitOfWorkImplementor(_factory, _session);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var transaction = _uow.BeginTransaction();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.IsNotNull(transaction);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>I expect that during execution of the method under test the BeginTransaction method of the NHibernate session is called. After calling <b>BeginTransaction</b> on the UoW (in the Playback phase) I additionally test whether I get a not-null transaction.</p> <p>I also want to be able to start a transaction and define an <a href="http://www.hibernate.org/hib_docs/nhibernate/html/transactions.html">isolation level for the transaction</a>. The corresponding test might look like</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_BeginTransaction_specifying_isolation_level()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var isolationLevel = IsolationLevel.Serializable;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">using</span>(_mocks.Record())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> { </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Expect.Call(_session.BeginTransaction(isolationLevel)).Return(<span style="color:#0000ff;">null</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">using</span> (_mocks.Playback())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _uow = <span style="color:#0000ff;">new</span> UnitOfWorkImplementor(_factory, _session);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var transaction = _uow.BeginTransaction(isolationLevel);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Assert.IsNotNull(transaction);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>To fulfill the test(s) I just have to create a new instance of a generic transaction and pass the result of the <i>_session.BeginTransaction</i> call to the constructor (that is: a NHibernate ITransaction object)</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> IGenericTransaction BeginTransaction()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> <span style="color:#0000ff;">new</span> GenericTransaction(_session.BeginTransaction());</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> IGenericTransaction BeginTransaction(IsolationLevel isolationLevel)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">return</span> <span style="color:#0000ff;">new</span> GenericTransaction(_session.BeginTransaction(isolationLevel));</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>The methods each return me an instance of type GenericTransaction which I can use in my code and call their respective commit or rollback methods if appropriate.</p> <p>The <b>TransactionalFlush</b> method should flush the content of the NHibernate session to the database wrapped inside a transaction. Let&#39;s define the test(s) for it</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_execute_TransactionalFlush()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var tx = _mocks.CreateMock&lt;ITransaction&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var session = _mocks.DynamicMock&lt;ISession&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> SetupResult.For(session.BeginTransaction(IsolationLevel.ReadCommitted)).Return(tx);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _uow = _mocks.PartialMock&lt;UnitOfWorkImplementor&gt;(_factory, _session);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">using</span> (_mocks.Record())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Expect.Call(tx.Commit);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Expect.Call(tx.Dispose);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">using</span> (_mocks.Playback())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _uow = <span style="color:#0000ff;">new</span> UnitOfWorkImplementor(_factory, session);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _uow.TransactionalFlush();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_execute_TransactionalFlush_specifying_isolation_level()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var tx = _mocks.CreateMock&lt;ITransaction&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var session = _mocks.DynamicMock&lt;ISession&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> SetupResult.For(session.BeginTransaction(IsolationLevel.Serializable)).Return(tx);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _uow = _mocks.PartialMock&lt;UnitOfWorkImplementor&gt;(_factory, session);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">using</span> (_mocks.Record())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Expect.Call(tx.Commit);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Expect.Call(tx.Dispose);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">using</span> (_mocks.Playback())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _uow.TransactionalFlush(IsolationLevel.Serializable);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>and the implementation is straight forward</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> TransactionalFlush()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> TransactionalFlush(IsolationLevel.ReadCommitted);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> TransactionalFlush(IsolationLevel isolationLevel)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> IGenericTransaction tx = BeginTransaction(isolationLevel);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">try</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#008000;">//forces a flush of the current unit of work</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> tx.Commit();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">catch</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> tx.Rollback();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">throw</span>;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">finally</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> tx.Dispose();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Note that when you don&#39;t provide an explicit transaction isolation level our implementation automatically assumes an isolation level equal to &quot;read commited&quot;. Note also that if the Commit of the transaction fails the transaction is rolled back.</p> <p><b>Important</b>: In the case of an exception during <b>TransactionalFlush</b> do not try to reuse the current unit of work since the session is in an <a href="http://www.hibernate.org/42.html#A3">inconsistent state</a> and must be closed. Thus abandon this UoW and start a new one.</p> <p>To increase the usability of the UoW instance a little bit I add the following members (which need no further explanation)</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">bool</span> IsInActiveTransaction</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> _session.Transaction.IsActive;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> IUnitOfWorkFactory Factory</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get { <span style="color:#0000ff;">return</span> _factory; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> ISession Session</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> get { <span style="color:#0000ff;">return</span> _session; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Flush()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _session.Flush();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>That&#39;s it! We have now a simple implementation of the Unit of Work pattern for NHibernate. Let me provide an overall picture of our implementation</p> <p><img src="/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/nhibernate.UoW/UoW-overview.png" alt="" /></p> <p><b>Please remember</b>: In this current version the UoW is strictly NOT thread-safe! But I&#39;ll show you how to make it thread-safe in the next post.&nbsp; </p> <h2>Using the Unit of Work</h2> <p>In the following section I&#39;ll quickly show the typical usage of the UoW. As usual I do this via TDD. I want to demonstrate how one can define a new instance of an entity and add it to the database. In this case the entity is a simple Person type object.</p> <p>Let us first set up a test fixture as follows</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">using</span> System;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">using</span> System.Reflection;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">using</span> NHibernate.Tool.hbm2ddl;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">using</span> NUnit.Framework;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">namespace</span> NHibernateUnitOfWork.Tests</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> [TestFixture]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> Test_usage_of_UnitOfWork</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> [SetUp]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> SetupContext()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> UnitOfWork.Configuration.AddAssembly(Assembly.GetExecutingAssembly());</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">new</span> SchemaExport(UnitOfWork.Configuration).Execute(<span style="color:#0000ff;">false</span>, <span style="color:#0000ff;">true</span>, <span style="color:#0000ff;">false</span>, <span style="color:#0000ff;">false</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>In the <b>SetupContext</b> method I first add the current assembly (the one in which this test is running) as a source of the <i>schema mapping information</i> to the configuration of NHibernate (which I can access via our <b>UnitOfWork</b> class). It is important that this call is done prior to the creation of the <b>SessionFactory</b> (that is prior to using a session).</p> <p>After extending the configuration I use the <b>SchemaExport</b> class of NHibernate to automatically generate the database schema for me.</p> <p>But wait: up to now I have not defined any schema at all! So let&#39;s do it now. Let&#39;s define a simple <b>Person</b> entity. Add a new file <b>Person.cs</b> to the test project and add the following code</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> Person</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">virtual</span> Guid Id { get; set; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">virtual</span> <span style="color:#0000ff;">string</span> Name { get; set; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">virtual</span> DateTime Birthdate { get; set; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>add an XML mapping document called <b>Person.hbm.xml</b> to the test project and define the following content</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">&lt;?</span><span style="color:#800000;">xml</span> <span style="color:#ff0000;">version</span><span style="color:#0000ff;">=&quot;1.0&quot;</span> <span style="color:#ff0000;">encoding</span><span style="color:#0000ff;">=&quot;utf-8&quot;</span> ?<span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">&lt;</span><span style="color:#800000;">hibernate-mapping</span> <span style="color:#ff0000;">xmlns</span><span style="color:#0000ff;">=&quot;urn:nhibernate-mapping-2.2&quot;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#ff0000;">assembly</span><span style="color:#0000ff;">=&quot;NHibernateUnitOfWork.Tests&quot;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#ff0000;">namespace</span><span style="color:#0000ff;">=&quot;NHibernateUnitOfWork.Tests&quot;</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">class</span> <span style="color:#ff0000;">name</span><span style="color:#0000ff;">=&quot;Person&quot;</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">id</span> <span style="color:#ff0000;">name</span><span style="color:#0000ff;">=&quot;Id&quot;</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">generator</span> <span style="color:#ff0000;">class</span><span style="color:#0000ff;">=&quot;guid&quot;</span><span style="color:#0000ff;">/&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">id</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">property</span> <span style="color:#ff0000;">name</span><span style="color:#0000ff;">=&quot;Name&quot;</span> <span style="color:#ff0000;">not-null</span><span style="color:#0000ff;">=&quot;true&quot;</span> <span style="color:#ff0000;">length</span><span style="color:#0000ff;">=&quot;50&quot;</span><span style="color:#0000ff;">/&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">&lt;</span><span style="color:#800000;">property</span> <span style="color:#ff0000;">name</span><span style="color:#0000ff;">=&quot;Birthdate&quot;</span> <span style="color:#ff0000;">not-null</span><span style="color:#0000ff;">=&quot;true&quot;</span><span style="color:#0000ff;">/&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">class</span><span style="color:#0000ff;">&gt;</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">&lt;/</span><span style="color:#800000;">hibernate-mapping</span><span style="color:#0000ff;">&gt;</span></pre> </div> </div> <p>Don&#39;t forget to set the &#39;Build Action&#39; property of this item to <b>&#39;Embedded Resource&#39;</b>!</p> <p>Now we can write a test to insert a new person instance into the database.</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_add_a_new_instance_of_an_entity_to_the_database()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">using</span>(UnitOfWork.Start())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var person = <span style="color:#0000ff;">new</span> Person {Name = <span style="color:#006080;">&quot;John Doe&quot;</span>, Birthdate = <span style="color:#0000ff;">new</span> DateTime(1915, 12, 15)};</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> UnitOfWork.CurrentSession.Save(person);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> UnitOfWork.Current.TransactionalFlush();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>When running this test the output generated by NHibernate looks similar to this</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">NHibernate: INSERT <span style="color:#0000ff;">INTO</span> Person (Name, Birthdate, Id) <span style="color:#0000ff;">VALUES</span> (@p0, @p1, @p2); </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">@p0 = <span style="color:#006080;">&#39;John Doe&#39;</span>, @p1 = <span style="color:#006080;">&#39;15.12.1915 00:00:00&#39;</span>, </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">@p2 = <span style="color:#006080;">&#39;bb72ae4c-7d64-4c16-84dc-c0ba2c7d306b&#39;</span></pre> </div> </div> <h2>Summary</h2> <p>I have shown you a possible implementation of the <b>Unit of Work</b> pattern for NHibernate. The implementation has been developed by using <a href="http://en.wikipedia.org/wiki/Test-driven_development">TDD</a>. The usage of a Unit of Work pattern simplifies the data manipulation tasks and hides the infrastructure details from the consumer of the UoW. NHibernate offers it&#39;s own implementation of the UoW in the form of the Session object. But NHibernate is just one of several possible ORM tools. With this implementation of the UoW pattern we have hidden most of the specifics of NHibernate an provide a generic interface to the consumer of the UoW.</p> <p>There are just two open points </p> <ul> <li>our implementation in <b>not</b> thread safe </li> <li>we still need to access the session object (through UnitOfWork.CurrentSession) to read or modify our entites </li> </ul> <p>The former I&#39;ll cover in the third part of this article and the latter problem can be solved by introducing a (generic) repository.</p> <h1>Part 3</h1> <h2>Introduction</h2> <p>In the previous two chapters<a href="http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/04/13/nhibernate-and-the-unit-of-work-pattern-part-2.aspx"></a> I introduced the Unit of Work pattern and developed a working version based on NHibernate. One weak point of the shown implementation is that it is strictly <i>non thread safe</i>. In NHibernate the <b>session object</b> takes the role of the Unit of Work container. The session object is not thread safe! That is a session instance may not be accessed from different threads. If your application is running on multiple threads (typically an application running on the server) then you have to open a new session instance for each running thread. </p> <p>In this post I want to improve the implementation of the Unit of Work pattern such as that it is thread safe. The class which starts a new unit of work is a static class. All static members of this class are accessible from each thread of the application domain in which your application is running. Now fortunately .NET provides us a mean to define pseudo static fields in a type which are local to a single thread. That is this state is not shared between different threads. Each thread has its own thread static state. To make a field thread static one has to decorate it with the [<b>ThreadStatic</b>] attribute. </p> <p>The easiest and most pragmatic approach would now be to just decorate our _<b>innerUnitOfWork</b> field of the <b>UnitOfWork </b>class with the [ThreadStatic] attribute. But eventually we want to keep additional state in our Unit of Work. Thus we implement a special <b>Data</b> class which is a kind of a wrapper around a Hashtable. </p> <h2>Container for Thread Static State</h2> <p>There are 2 possible scenarios I want to discuss. You either develop an application with a web client or an application with a windows client (e.g. WinForms). </p> <p>In a web application one has the so called <b>Http context</b> for each request. Multiple requests from different clients can run at the same but each of them runs on a different thread and has it&#39;s own context. In this situation we store the data relevant to the unit of work in the context of the request.</p> <p>In a windows client application (i.e. Smart Client Application) on the other hand we have a single client that might run on different threads at the same time. In this situation we &quot;attach&quot; the data relevant to the unit of work in so called thread-static fields. A thread-static field is not shared between different threads in the same application. To make a (static) field thread-static we have to just decorate it with a [<b>ThreadStatic</b>] attribute.</p> <p>In our Unit of Work implementation we have the static UnitOfWork class which contains a static field _<b>innerUnitOfWork</b> of type <b>IUnitOfWork</b>. We now need to change <i>this</i> since this kind of implementation is not thread safe. Since we might want to save other data in a thread safe way as well (not just the current instance of the unit of work) we choose a slightly more sophisticated solution.</p> <p>Let&#39;s define a static class <b>Local</b> which encapsulates the details whether we run a web- or a win-application. This class has just one (static) read-only property Data of type <b>ILocalData</b>.</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">using</span> System;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">using</span> System.Collections;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">namespace</span> NHibernateUnitOfWork</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">class</span> Local</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">readonly</span> ILocalData _data = <span style="color:#0000ff;">new</span> LocalData();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> ILocalData Data</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> get { <span style="color:#0000ff;">return</span> _data; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">class</span> LocalData : ILocalData</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#008000;">// implementation details to de defined</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>All details of our implementation are now &quot;hidden&quot; in the class <b>LocalData</b> which we choose to be a private child class of the <b>Local</b> class. We now want to be able to save into and read data from this local container via a key, e.g.</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">Local.Data[<span style="color:#006080;">&quot;some key&quot;</span>] = someValue;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#008000;">// or</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">otherValue = Local.Data[<span style="color:#006080;">&quot;other key&quot;</span>];</pre> </div> </div> <p>This should be in a thread safe way. Obviously the above sample client code implies that we use some kind of <i>dictionary</i> to internally store our data.</p> <p>As usual we formulate our intention in a unit test which might look like this</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">using</span> System;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">using</span> NUnit.Framework;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">namespace</span> NHibernateUnitOfWork.Tests</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> [TestFixture]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> LocalData_Fixture</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> [Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_store_values_in_local_data()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Local.Data[<span style="color:#006080;">&quot;one&quot;</span>] = <span style="color:#006080;">&quot;This is a string&quot;</span>;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Local.Data[<span style="color:#006080;">&quot;two&quot;</span>] = 99.9m;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var person = <span style="color:#0000ff;">new</span> Person {Name = <span style="color:#006080;">&quot;John Doe&quot;</span>, Birthdate = <span style="color:#0000ff;">new</span> DateTime(1991, 1, 15)};</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Local.Data[1] = person;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Assert.AreEqual(3, Local.Data.Count);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreEqual(<span style="color:#006080;">&quot;This is a string&quot;</span>, Local.Data[<span style="color:#006080;">&quot;one&quot;</span>]);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Assert.AreEqual(99.9m, Local.Data[<span style="color:#006080;">&quot;two&quot;</span>]);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreSame(person, Local.Data[1]);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>The test shows that I want to be able to not only store basic types but any complex type in my local data container. In this case a string, an integer and an instance of a Person class. The Person class is very basic at looks like follows</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> Person</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">virtual</span> Guid Id { get; set; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">virtual</span> <span style="color:#0000ff;">string</span> Name { get; set; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">virtual</span> DateTime Birthdate { get; set; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>Please also note that I use keys of different type (<i>string</i> and <i>int</i>). </p> <h3>Implementation for Smart Client Applications</h3> <p>Let&#39;s first assume that we want to provide a thread safe unit of work implementation for the smart client application. Then the most basic implementation to fulfill&nbsp; this test is</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">private</span> <span style="color:#0000ff;">class</span> LocalData : ILocalData</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">static</span> Hashtable _localData = new Hashtable();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">object</span> <span style="color:#0000ff;">this</span>[<span style="color:#0000ff;">object</span> key]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get { <span style="color:#0000ff;">return</span> _localData[key]; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> set { _localData[key] = <span style="color:#0000ff;">value</span>; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">int</span> Count</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get { <span style="color:#0000ff;">return</span> _localData.Count; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>I just take a hash table as local storage and define an indexer property and a Count property (Note: a <i>HashTable</i> is an often used implementation of a <i>Dictionary</i>).</p> <p>We want to also be able to <b>clear</b> the content of the local store and thus we define the following test</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_clear_local_data()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Local.Data[<span style="color:#006080;">&quot;one&quot;</span>] = <span style="color:#006080;">&quot;This is a string&quot;</span>;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Local.Data[<span style="color:#006080;">&quot;two&quot;</span>] = 99.9m;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreEqual(2, Local.Data.Count);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Local.Data.Clear();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreEqual(0, Local.Data.Count);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>The code to fulfill this test is trivial, just add the code snippet below to the <b>LocalData</b> class</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Clear()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _localData.Clear();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>Unfortunately the test still faults when run! This is because the local data storage is static and all test methods access the same container we have a &quot;side effect&quot; which we must now compensate. We can do it by just clearing the local data container before each test. Add this code to the test fixture class to compensate the side effect</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[SetUp]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> SetupContext()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Local.Data.Clear(); <span style="color:#008000;">// start side-effect free!</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Re-run all tests. They should now all pass...</p> <p>And now comes the &quot;tricky&quot; part of the implementation where we want to guarantee that our local data store is indeed <b>thread safe</b>. Let&#39;s first define a test for this scenario</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">private</span> ManualResetEvent _event;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Local_data_is_thread_local()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Console.WriteLine(<span style="color:#006080;">&quot;Starting in main thread {0}&quot;</span>, Thread.CurrentThread.ManagedThreadId);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Local.Data[<span style="color:#006080;">&quot;one&quot;</span>] = <span style="color:#006080;">&quot;This is a string&quot;</span>;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreEqual(1, Local.Data.Count);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _event = <span style="color:#0000ff;">new</span> ManualResetEvent(<span style="color:#0000ff;">false</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var backgroundThread = <span style="color:#0000ff;">new</span> Thread(RunInOtherThread);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> backgroundThread.Start();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#008000;">// give the background thread some time to do its job</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Thread.Sleep(100);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#008000;">// we still have only one entry (in this thread)</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Assert.AreEqual(1, Local.Data.Count);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Console.WriteLine(<span style="color:#006080;">&quot;Signaling background thread from main thread {0}&quot;</span>, Thread.CurrentThread.ManagedThreadId);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _event.Set();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> backgroundThread.Join();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">private</span> <span style="color:#0000ff;">void</span> RunInOtherThread()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Console.WriteLine(<span style="color:#006080;">&quot;Starting (background-) thread {0}&quot;</span>, Thread.CurrentThread.ManagedThreadId);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#008000;">// initially the local data must be empty for this NEW thread!</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreEqual(0, Local.Data.Count);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Local.Data[<span style="color:#006080;">&quot;one&quot;</span>] = <span style="color:#006080;">&quot;This is another string&quot;</span>;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreEqual(1, Local.Data.Count);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Console.WriteLine(<span style="color:#006080;">&quot;Waiting on (background-) thread {0}&quot;</span>, Thread.CurrentThread.ManagedThreadId);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _event.WaitOne();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Console.WriteLine(<span style="color:#006080;">&quot;Ending (background-) thread {0}&quot;</span>, Thread.CurrentThread.ManagedThreadId);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>In the above code I run two threads in parallel, the thread on which the test is running (let&#39;s call it the <b>main thread</b>) and an additional <b>background thread</b>. The code which is executed in the background thread is implemented in the helper method <b>RunInOtherThread</b>. To be able to synchronize the two threads I use an <b>Event</b>, in this case a <b>ManualResetEvent</b>. I have put some <i>Console.WriteLine</i> statements in the code for debugging purposes.</p> <p>In the main thread I add some data to the local data store. Then I spin up the background thread. In the background thread I first test that my (thread-) local data store is empty and then also fill in some data. With the <b>Assert</b> statements I test that we really have a thread safe behavior.</p> <p>The only change needed to make my implementation thread safe is to decorate the static field _localData with the [ThreadStatic] attribute.</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[ThreadStatic]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">private</span> <span style="color:#0000ff;">static</span> Hashtable _localData = <span style="color:#0000ff;">new</span> Hashtable();</pre> </div> </div> <p>When the test is run it should pass and produce an output similar to this</p> <p><img src="/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/nhibernate.UoW/UoW-Multi_2D00_Threading-UnitTest.png" alt="" /></p> <h3>Implementation for Web</h3> <p>As mentioned above in this scenario we want to store our local data in the context of the current HTTP request. </p> <p>First I want to provide an indicator whether I am running in web and thus I add the following to the code snippet to the <b>LocalData</b> class</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">bool</span> RunningInWeb</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get { <span style="color:#0000ff;">return</span> HttpContext.Current != <span style="color:#0000ff;">null</span>; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>Here I use the <b>HttpContext</b> class of the .NET framework (namespace <i>System.Web</i>). It&#39;s static property <b>Current</b> is equal to null if we do not run in the context of a web application.</p> <p>To abstract the details of the context (web- or smart client application) I define a private read-only property <b>LocalHashtable</b> as below</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">private</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">readonly</span> <span style="color:#0000ff;">object</span> LocalDataHashtableKey = <span style="color:#0000ff;">new</span> <span style="color:#0000ff;">object</span>();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">private</span> <span style="color:#0000ff;">static</span> Hashtable LocalHashtable</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">if</span> (!RunningInWeb)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">if</span> (_localData == <span style="color:#0000ff;">null</span>)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _localData = <span style="color:#0000ff;">new</span> Hashtable();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> _localData;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">else</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var web_hashtable = HttpContext.Current.Items[LocalDataHashtableKey] <span style="color:#0000ff;">as</span> Hashtable;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">if</span> (web_hashtable == <span style="color:#0000ff;">null</span>)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> web_hashtable = <span style="color:#0000ff;">new</span> Hashtable();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> HttpContext.Current.Items[LocalDataHashtableKey] = web_hashtable;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> web_hashtable;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>In this code I use the <b>RunningInWeb</b> helper method to distinguish the two cases. In the case of NOT running in web context I test whether my thread static _<b>localData</b> field is equal to null, and If so I initialize it with a new instance of type <b>Hashtable</b>. I then return this instance. On the other hand, when running in web context I try to access a hash table instance in the <b>Items</b> collection of the current Http context. If I do not find such an instance then I create a new one and put it into the items collection of the current context. I then return the instance.</p> <p>Now I have to locate every place in the <b>LocalData</b> class where I access the _<b>localData</b> field directly and replace it with a reference to the <b>LocalHashtable</b> property. E.g. the indexer will have to be changed as follows</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">object</span> <span style="color:#0000ff;">this</span>[<span style="color:#0000ff;">object</span> key]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get { <span style="color:#0000ff;">return</span> LocalHashtable[key]; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> set { LocalHashtable[key] = <span style="color:#0000ff;">value</span>; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Our thread- and/or Http context local data store is now complete and we can use it in our <b>UnitOfWork</b> class.</p> <h2>Make Unit Of Work implementation thread safe</h2> <p>To make our unit of work implementation thread safe we change the implementation of our static <b>UnitOfWork</b> class as shown below</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">class</span> UnitOfWork</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">readonly</span> IUnitOfWorkFactory _unitOfWorkFactory = <span style="color:#0000ff;">new</span> UnitOfWorkFactory();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> Configuration Configuration</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get { <span style="color:#0000ff;">return</span> _unitOfWorkFactory.Configuration; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">const</span> <span style="color:#0000ff;">string</span> CurrentUnitOfWorkKey = <span style="color:#006080;">&quot;CurrentUnitOfWork.Key&quot;</span>;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">static</span> IUnitOfWork CurrentUnitOfWork</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> get { <span style="color:#0000ff;">return</span> Local.Data[CurrentUnitOfWorkKey] <span style="color:#0000ff;">as</span> IUnitOfWork; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> set { Local.Data[CurrentUnitOfWorkKey] = <span style="color:#0000ff;">value</span>; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> IUnitOfWork Current</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> get</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var unitOfWork = CurrentUnitOfWork;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">if</span> (unitOfWork == <span style="color:#0000ff;">null</span>)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">throw</span> <span style="color:#0000ff;">new</span> InvalidOperationException(<span style="color:#006080;">&quot;You are not in a unit of work&quot;</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> unitOfWork;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">bool</span> IsStarted</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get { <span style="color:#0000ff;">return</span> CurrentUnitOfWork != <span style="color:#0000ff;">null</span>; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> ISession CurrentSession</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> get { <span style="color:#0000ff;">return</span> _unitOfWorkFactory.CurrentSession; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">internal</span> set { _unitOfWorkFactory.CurrentSession = <span style="color:#0000ff;">value</span>; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> IUnitOfWork Start()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">if</span> (CurrentUnitOfWork != <span style="color:#0000ff;">null</span>)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">throw</span> <span style="color:#0000ff;">new</span> InvalidOperationException(<span style="color:#006080;">&quot;You cannot start more than one unit of work at the same time.&quot;</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var unitOfWork = _unitOfWorkFactory.Create();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> CurrentUnitOfWork = unitOfWork;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> unitOfWork;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">void</span> DisposeUnitOfWork(IUnitOfWorkImplementor unitOfWork)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> CurrentUnitOfWork = <span style="color:#0000ff;">null</span>;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>As you can see the field _<b>innerUnitOfWork</b> has gone and is replaced by a private property <b>CurrentUnitOfWork</b>. This property in turn uses the previously defined <b>Local </b>class to store the current unit of work item. </p> <p>Note that there is one place in our unit tests that makes a reference to the field _<b>innerUnitOfWork</b> and must thus be changed. It&#39;s the method <b>ResetUnitOfWork</b> in the class <b>UnitOfWork_With_Factory_Fixture</b>. The new implementation is</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">private</span> <span style="color:#0000ff;">void</span> ResetUnitOfWork()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#008000;">// assert that the UnitOfWork is reset</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var propertyInfo = <span style="color:#0000ff;">typeof</span>(UnitOfWork).GetProperty(<span style="color:#006080;">&quot;CurrentUnitOfWork&quot;</span>,</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> BindingFlags.Static | BindingFlags.SetProperty | BindingFlags.NonPublic);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> propertyInfo.SetValue(<span style="color:#0000ff;">null</span>, <span style="color:#0000ff;">null</span>, <span style="color:#0000ff;">null</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>When run, all tests should again pass. So now our implementation of the unit of work is thread safe.</p> <p>You can find the full code <a href="http://hibernatingrhinos.googlecode.com/svn/trunk/UnitOfWork/">here</a>.</p> <p>&nbsp;</p> <p>&nbsp;</p>NHibernate and the Unit of Work Patternhttp://nhforge.org/wikis/patternsandpractices/nhibernate-and-the-unit-of-work-pattern/revision/1.aspxTue, 23 Sep 2008 19:39:53 GMT45f813f2-f1c4-4eda-a619-288e3cadc793:152gabriel.schenkerhttp://nhforge.org/wikis/patternsandpractices/nhibernate-and-the-unit-of-work-pattern/comments.aspx<h2>Introduction</h2> <p>Martin Fowler <a href="http://martinfowler.com/eaaCatalog/unitOfWork.html">writes</a>: </p> <p>&quot;When you&#39;re pulling data in and out of a database, it&#39;s important to keep track of what you&#39;ve changed; otherwise, that data won&#39;t be written back into the database. Similarly you have to insert new objects you create and remove any objects you delete.&quot;</p> <p>and</p> <p>&quot;A <strong>Unit of Work</strong> keeps track of everything you do during a <em>business transaction</em> that can affect the database. When you&#39;re done, it figures out everything that needs to be done to alter the database as a result of your work.&quot;</p> <p>In NHibernate we have the <strong>Session</strong> object which is a Unit of Work (UoW) container. The session object keeps track of all objects you load, new objects you add, existing objects you delete and changes you make to any of these objects. Only when <strong>flushing</strong> the session will the database be altered (that is: will the necessary create, update and delete statements be sent to the database).</p> <p>Now, working directly with the NHibernate session object makes absolute sense. But some times you rather want to abstract the data manipulation interface from a specific infrastructure implementation &agrave; la NHibernate.</p> <p><strong>Note</strong>: most of the design ideas and implementation details presented here originate from <a href="http://www.ayende.com/">Ayende</a>&#39;s UnitOfWork implemented in the <strong>Rhino.Commons</strong> which you can get <a href="http://rhino-tools.svn.sourceforge.net/svnroot/rhino-tools/trunk">here</a>.</p> <h2>Design and Implementation (TDD)</h2> <h3>Some thought about TDD</h3> <p>I want to implement a UnitOfWork pattern for NHibernate and I want to do it by using <a href="http://en.wikipedia.org/wiki/Test-driven_development">TDD</a>. For a beginner (like I was myself not so long ago) it seems unnatural at the beginning. We introduce a huge overhead you might think. You might also think that we have to write at least double the code as when doing the development without TDD. But wait until you have to start to debug your application... or until the customer wants to have something changed in the application... or until you have to re-factor you application... Then you will immediately see and feel the benefits of a good test coverage.</p> <h3>Attention: Multi-Threading ahead</h3> <p>Please not that the implementation presented here is strictly <strong>NOT</strong> thread safe!!! I want to reduce the complexity of this first implementation. But <strong>I promise</strong> that in a following post I&#39;ll show you how to make the implementation of the unit of work pattern thread safe and thus useful for e.g. Web scenarios.</p> <h3>The UnitOfWork Class</h3> <p>To start with: I want to have an easy way to <strong>start</strong> a new UoW, in any place of my application have access to the <strong>current</strong> UoW and <strong>commit</strong> the <em>business transaction</em> represented by my UoW. We can do this with a static class called UnitOfWork</p> <p><a><img style="border-width:0px;" alt="image" border="0" height="179" width="471" /></a></p> <p>The method start creates and returns an instance of a <strong>UnitOfWorkImplementor</strong> class which implements the interface <strong>IUnitOfWork</strong>. As you can see then interface IUnitOfWork inherits from IDisposable. So we can define that the <em>business transaction</em> is ended when the UoW is disposed. Now, if we do nothing else then nothing should happen, that is no changes should be propagated to the database. To commit a <em>business transaction</em> we have to explicitly call a method of the UoW. Let&#39;s call this method <strong>TransactionalFlush</strong>. In doing so all changes recorded by the UoW are committed to the database in one go.</p> <p>Now let&#39;s start to implement this! We are doing TDD, aren&#39;t we? So we will write our first test (if you are not sure how to best setup a new solution for TDD please consult <a href="http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/04/06/how-to-setup-a-new-solution.aspx">this</a> post). I define a new solution with two projects as follows</p> <p><a><img style="border-width:0px;" alt="image" border="0" height="135" width="304" /></a></p> <p>Add a class UnitOfWork_Fixture.cs to the test project and implement the first test like this</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[TestFixture]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> UnitOfWork_Fixture</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">readonly</span> MockRepository _mocks = <span style="color:#0000ff;">new</span> MockRepository();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> [Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_Start_UnitOfWork()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> IUnitOfWork uow = UnitOfWork.Start();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Of course this test will not compile since you don&#39;t have the types UnitOfWork and IUnitOfWork defined yet. Let <a href="http://www.jetbrains.com/resharper/">Resharper</a> create them for you (or implement them by hand)</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">class</span> UnitOfWork</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> IUnitOfWork Start()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">throw</span> <span style="color:#0000ff;">new</span> NotImplementedException();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> IUnitOfWork Current { get; <span style="color:#0000ff;">private</span> set; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">interface</span> IUnitOfWork : IDisposable</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Now the test will compile but it will fail! Of course, you haven&#39;t implemented the Start method so far. In this method we must now create a new UoW and return it to the caller. A UoW is a complex beast and should therefore be constructed in a factory. So let&#39;s define a factory Interface IUnitOfWorkFactory with a method Create which returns a UoW implementing the interface IUnitOfWork.</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">interface</span> IUnitOfWorkFactory</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> IUnitOfWork Create();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>since we want to test our UnitOfWork class in isolation we have to mock all other dependencies line the unit of work factory. I&#39;ll use <strong>Rhino.Mocks</strong> as my mocking framework (Please refer to documentation <a href="http://www.ayende.com/wiki/Rhino+Mocks+Documentation.ashx">here</a>). I want to test that when calling the start method of the UnitOfWork class the factory gets called. So I extend my test function</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_Start_UnitOfWork()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var factory = _mocks.DynamicMock&lt;IUnitOfWorkFactory&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var unitOfWork = _mocks.DynamicMock&lt;IUnitOfWork&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#008000;">// brute force attack to set my own factory via reflection</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var fieldInfo = <span style="color:#0000ff;">typeof</span>(UnitOfWork).GetField(<span style="color:#006080;">&quot;_unitOfWorkFactory&quot;</span>, </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> BindingFlags.Static | BindingFlags.SetField | BindingFlags.NonPublic);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> fieldInfo.SetValue(<span style="color:#0000ff;">null</span>, factory);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">using</span>(_mocks.Record())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Expect.Call(factory.Create()).Return(unitOfWork);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">using</span>(_mocks.Playback())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var uow = UnitOfWork.Start();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>In the first two lines of code I mock the external dependencies of the UnitOfWork class. Then I do something you should not do very often (but I have good reasons doing so here and I promise it&#39;s the only time I&#39;ll do it in this project...). I set a private field of the UnitOfWork class with a value by using reflection. I could implement a public setter in the class but as I would only need it for this test and I want to keep the class interface as simple as possible I chose to do it via reflection.</p> <p>In the&nbsp; record phase I define my expectation (namely that the factory create method is called) and in the playback phase I invoke the Start method which I want to test. The test will compile but fail to execute. I have not yet defined the private static field _unitOfWorkFactory and I also do not call the factory. So let&#39;s modify our code...</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">class</span> UnitOfWork</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">static</span> IUnitOfWorkFactory _unitOfWorkFactory;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">static</span> IUnitOfWork _innerUnitOfWork;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> IUnitOfWork Start()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _innerUnitOfWork = _unitOfWorkFactory.Create();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> _innerUnitOfWork;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> IUnitOfWork Current { get; <span style="color:#0000ff;">private</span> set; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>now the test will pass.</p> <p>Since in all our test regarding the UnitOfWork class we will always need it with an injected factory we define a new test fixture with a context setup for our specific needs. We put the respective code in the <strong>SetupContext</strong> and <strong>TearDownContext</strong> methods</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[TestFixture]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">class</span> UnitOfWork_With_Factory_Fixture</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> <span style="color:#0000ff;">readonly</span> MockRepository _mocks = <span style="color:#0000ff;">new</span> MockRepository();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">private</span> IUnitOfWorkFactory _factory;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">private</span> IUnitOfWork _unitOfWork;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> [SetUp]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> SetupContext()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _factory = _mocks.DynamicMock&lt;IUnitOfWorkFactory&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _unitOfWork = _mocks.DynamicMock&lt;IUnitOfWork&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#008000;">// brute force attack to set my own factory via reflection</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var fieldInfo = <span style="color:#0000ff;">typeof</span>(UnitOfWork).GetField(<span style="color:#006080;">&quot;_unitOfWorkFactory&quot;</span>,</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> BindingFlags.Static | BindingFlags.SetField | BindingFlags.NonPublic);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> fieldInfo.SetValue(<span style="color:#0000ff;">null</span>, _factory);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _mocks.BackToRecordAll();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> SetupResult.For(_factory.Create()).Return(_unitOfWork);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _mocks.ReplayAll();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> [TearDown]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> TearDownContext()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _mocks.VerifyAll();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p><strong>Note</strong>: in the second last line of the <strong>SetupContext</strong> method we define that each time the method Create of the factory object is called (by the UnitOfWork Start method) we want it to return our predefined mocked _<strong>unitOfWork</strong> instance.</p> <p>Trying to start a UoW if there is already one active should throw a meaningful exception. This is the test</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Starting_UnitOfWork_if_already_started_throws()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> UnitOfWork.Start();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">try</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> UnitOfWork.Start();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">catch</span> (InvalidOperationException ex)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> { }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>As a consequence we have to extend our Start method in the UnitOfWork class</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> IUnitOfWork Start()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">if</span> (_innerUnitOfWork != <span style="color:#0000ff;">null</span>)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">throw</span> <span style="color:#0000ff;">new</span> InvalidOperationException(<span style="color:#006080;">&quot;You cannot start more than one unit of work at the same time.&quot;</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> </pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _innerUnitOfWork = _unitOfWorkFactory.Create();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> _innerUnitOfWork;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>Now I have another problem: After the test is finished the static field _<strong>innerUnitOfWork</strong> of my <strong>UnitOfWork</strong> class is set to a value other than <strong>null</strong>. This will have a undesired side effect to the following test. I have to reset this field. Again in this special case I&#39;ll do it via reflection to not clutter the interface of my class (static classes are difficult more complex to deal with in TDD than non static classes...). We do reset our UnitOfWork class in the TearDownContext method</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[TearDown]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> TearDownContext()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _mocks.VerifyAll();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#008000;">// assert that the UnitOfWork is reset</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var fieldInfo = <span style="color:#0000ff;">typeof</span>(UnitOfWork).GetField(<span style="color:#006080;">&quot;_innerUnitOfWork&quot;</span>,</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> BindingFlags.Static | BindingFlags.SetField | BindingFlags.NonPublic);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> fieldInfo.SetValue(<span style="color:#0000ff;">null</span>, <span style="color:#0000ff;">null</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>Next we want to be able to access the current unit of work. As usual we first implement a test</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_access_current_unit_of_work()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> IUnitOfWork uow = UnitOfWork.Start();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var current = UnitOfWork.Current;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.AreSame(uow, current);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>You can figure out what code you need to implement for the test to pass.</p> <p>We also want to assert that when accessing the current UoW if no UoW has been started that a meaningful exception is thrown</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Accessing_Current_UnitOfWork_if_not_started_throws()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">try</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> var current = UnitOfWork.Current;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">catch</span> (InvalidOperationException ex)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> { }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>now my implementation of the Current property in the UnitOfWork class is as follows</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> IUnitOfWork Current</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">if</span> (_innerUnitOfWork == <span style="color:#0000ff;">null</span>)</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">throw</span> <span style="color:#0000ff;">new</span> InvalidOperationException(<span style="color:#006080;">&quot;You are not in a unit of work.&quot;</span>);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> <span style="color:#0000ff;">return</span> _innerUnitOfWork;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Next we want a property on the class which tells us whether a UoW is started or not. The test for it</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_test_if_UnitOfWork_Is_Started()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> Assert.IsFalse(UnitOfWork.IsStarted);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> IUnitOfWork uow = UnitOfWork.Start();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Assert.IsTrue(UnitOfWork.IsStarted);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>It&#39;s getting boring isn&#39;t it... But this is the way <strong>TDD</strong> works. You always think (hard) on what you need and then you implement the test with which you can proof that you get it as you want it. Only then you implement the functionality needed to fulfill the test. If you do so you automatically follow the <strong>YAGNI</strong> principle (you ain&#39;t gona need it) that is you only implement the code you really need!</p> <p>We can fulfill the test like so</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> <span style="color:#0000ff;">bool</span> IsStarted</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get { <span style="color:#0000ff;">return</span> _innerUnitOfWork != <span style="color:#0000ff;">null</span>; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">}</pre> </div> </div> <p>The UnitOfWork class is now a perfect wrapper for the NHibernate session object. Though for some advance scenarios I would like to have access to the session object related to my UoW. As a consequence I&#39;ll implement a read only property CurrentSession in the UnitOfWork class. Lets again start with the test</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[Test]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> Can_get_valid_current_session_if_UoW_is_started()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">using</span> (UnitOfWork.Start())</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> {</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> ISession session = UnitOfWork.CurrentSession;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> Assert.IsNotNull(session);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>and the implementation</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">static</span> ISession CurrentSession</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> get { <span style="color:#0000ff;">return</span> _unitOfWorkFactory.CurrentSession; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#0000ff;">internal</span> set { _unitOfWorkFactory.CurrentSession = <span style="color:#0000ff;">value</span>; }</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>Note that I have just delegated the call to the factory class. Thus to make the test pass I have to add two additional lines to the SetupContext method of the test fixture where I mock a session object and setup the result for a call to the property CurrentSession of the factory.</p> <div> <div style="border-style:none;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">[SetUp]</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"><span style="color:#0000ff;">public</span> <span style="color:#0000ff;">void</span> SetupContext()</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">{</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _factory = _mocks.DynamicMock&lt;IUnitOfWorkFactory&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _unitOfWork = _mocks.DynamicMock&lt;IUnitOfWork&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _session = _mocks.DynamicMock&lt;ISession&gt;();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> <span style="color:#008000;">// brute force attack to set my own factory via reflection</span></pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> var fieldInfo = <span style="color:#0000ff;">typeof</span>(UnitOfWork).GetField(<span style="color:#006080;">&quot;_unitOfWorkFactory&quot;</span>,</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> BindingFlags.Static | BindingFlags.SetField | BindingFlags.NonPublic);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> fieldInfo.SetValue(<span style="color:#0000ff;">null</span>, _factory);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;">&nbsp;</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> _mocks.BackToRecordAll();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> SetupResult.For(_factory.Create()).Return(_unitOfWork);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;"> SetupResult.For(_factory.CurrentSession).Return(_session);</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:#f4f4f4;"> _mocks.ReplayAll();</pre> <pre style="border-style:none;margin:0em;padding:0px;overflow:visible;font-size:8pt;width:100%;color:black;line-height:12pt;font-family:consolas,&#39;Courier New&#39;,courier,monospace;background-color:white;">}</pre> </div> </div> <p>That&#39;s all we need for the moment regarding the UnitOfWork class. Next topics will be the the implementation of the UnitOfWorkFactory class and then of the UnitOfWorkImplementor class. The details will be presented in the next post to this blog. So keep ready...</p> <p>&nbsp;</p> <p>Part 2</p> <h2>Design and Implementation</h2> <h3>The Unit Of Work Factory</h3> <p>The creation of a unit of work instance is a complex process and as such is a good candidate for a factory.</p> <p>Since a UoW (Unit of Work) is basically a wrapper around a NHibernate session object I&#39;ll need to open such a session whenever I start a new UoW. But to be able to get such a session NHibernate has to be configured and a NHibernate Session Factory has to be available. The interface of my UoW factory is defined as follows</p> <p><a><img style="border-width:0px;" alt="image" border="0" height="236" width="214" /></a> </p> <p>&nbsp;</p> <p>&nbsp;</p>