<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Cirrus ABS &#187; C#</title>
	<atom:link href="http://www.cirrusabs.com/blog/tag/c/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.cirrusabs.com/blog</link>
	<description>NetCentered &#38; Internet Marketing Concepts.</description>
	<lastBuildDate>Thu, 15 Jul 2010 22:05:15 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Application Performance: Open Session In View Design Pattern</title>
		<link>http://www.cirrusabs.com/blog/application-performance-open-session-in-view-design-pattern/</link>
		<comments>http://www.cirrusabs.com/blog/application-performance-open-session-in-view-design-pattern/#comments</comments>
		<pubDate>02/22/2010</pubDate>
		<dc:creator>Jonathon Gottschalk</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[design pattern]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[open session in view]]></category>

		<guid isPermaLink="false">http://www.cirrusabs.com/blog/?p=191</guid>
		<description><![CDATA[
I have been developing applications for the web for over 10 years, and I now primarily focus my efforts on the server-side of application development using.NET.  Furthermore, I find myself devoting a considerable amount of effort towards making a sound architecture that can not only scale, but perform adequately under heavy load.  This need has [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone size-full wp-image-206" title="blueprint" src="http://www.cirrusabs.com/blog/wp-content/uploads/2010/02/blueprint.jpg" alt="blueprint" width="650" height="150" /></p>
<p>I have been developing applications for the web for over 10 years, and I now primarily focus my efforts on the server-side of application development using.NET.  Furthermore, I find myself devoting a considerable amount of effort towards making a sound architecture that can not only scale, but perform adequately under heavy load.  This need has resulted in much research towards optimizing database transactions, connections, and queries.</p>
<p><span id="more-191"></span></p>
<p>As a developer my interest in design patterns has also been quite involved, and the Open Session In View Design Pattern is one of those patterns whose implementation has always fascinated me as a truly innovative solution to an otherwise seeming complex problem.  This design pattern requires a solid understanding of database connections, transactions, and the MVC (Model-View-Controller) design pattern.</p>
<h2>Background</h2>
<p>First, let’s dissect the name of this design pattern to better understand where it originates. The “View” in the name of the pattern refers to the V in MVC. The View is the part of the MVC design pattern that renders output to the client’s machine. A web application designed with an MVC design pattern would render HTML into its View for the client’s browser to then display on their screen.</p>
<p>Next, we need to analyze the “Open Session” part of the name. This part of the name reflects the abstract nature of this design pattern. The database connection and transaction combine to form a database “session.” Thus, when a user wants to render the web page the application must initiate a “session” with the database to perform its work.</p>
<p>Also, you may wonder who even came up with this concept. I don’t claim to be a historian, but my knowledge of this design pattern comes from the creators of Hibernate in the Java world. My personal exposure to it has been with NHibernate (the .NET port of the popular ORM library), and you can read more about it here: <a href="https://www.hibernate.org/43.html">https://www.hibernate.org/43.html</a>.</p>
<h2>Explanation</h2>
<p>The basic concept of this design pattern is simple: when a user connects to the web server, the web application starts running code which creates the HTML they will eventually see (the View). When this user first connects, this causes a session to begin with the database, which opens a connection and starts a transaction. Then, the web application continues running through all of the necessary code to create the page and once it finishes, it commits the transaction and closes the database connection, which ends the session. All of the code that runs during the rendering of the HTML uses the same database connection and transaction. This means that every user who connects to the web server that causes application code to run will only ever initiate a single connection to the back-end database.</p>
<h3>Advantages</h3>
<p>This design pattern has advantages and disadvantages just like any other architectural decision you will make for your application. The advantages I can associate with this design pattern include, but are not limited to, the following:</p>
<ol>
<li><strong>Promotes Maintainability</strong><br />
I am a fan of short clean code, and this design pattern certainly emphasizes it. If you implement this design pattern in your application, you will quickly realize that a single entry point for retrieving your database connection and transaction certainly makes things a lot cleaner. It promotes the maintainability of your code by making that single point of entry the only area of interest if future updates to the application become necessary, which by proxy promotes the concept of refactoring.</li>
<li><strong>Increases Performance</strong><br />
If your application is opening database connections and transactions all over the place during the normal execution of the view, you are most definitely going to see a performance gain by using this pattern. One of the largest overhead penalties that your application can incur is the creation and destruction of database connections. This design pattern isolates it down to a single connection and transaction, thus eliminating the overhead normally associated with creating and destroying the connection.</li>
<li><strong>Easy to Understand</strong><br />
The design pattern, unlike some more abstract ones I have been exposed to, is far easier to comprehend because you can actually describe it both visually and verbally to another developer who is not familiar with it. I know this may seem like a rather insignificant selling point for this design pattern, but I am always one to promote simple to understand code that I will have to explain and teach to junior developers.</li>
<li><strong>Database and Programming Language Neutral</strong><br />
The design pattern is not specific to .NET – you can just as easily demonstrate its implementation in PHP, Classic ASP, Java, and almost any other language. In fact, it is not even web-specific – the design pattern can be adapted to an application context just as easily as it can be adapted to a web context. Furthermore, it is also not database specific – you could utilize this design pattern with any database imaginable (MySQL, Oracle, SQL Server, Access, etc) with the same result.</li>
<li><strong>Does not truly rely on MVC</strong><br />
Although the background of this design pattern is based on the View part of the MVC design pattern, you can usually find a way to retrofit existing applications with this design pattern. It provides a viable option when examining performance problems with legacy applications.</li>
<li><strong>Reduces Concurrency Issues</strong><br />
This design pattern also helps reduce concurrency issues by maintaining a single transaction the whole time the view is rendered. This means that changes to the database by other threads should not affect the output, unless you are doing something very custom with your isolation levels. For more information about the impact of isolation levels and their impact in a multi-user environment, take a look at this article: <a href="http://sqlblogcasts.com/blogs/tonyrogerson/archive/2006/11/16/1345.aspx">http://sqlblogcasts.com/blogs/tonyrogerson/archive/2006/11/16/1345.aspx</a>.</li>
</ol>
<h3>Disadvantages</h3>
<p>This design pattern, despite many of its seeming advantages, also has drawbacks. I will try to enumerate through some of the ones I have encountered when utilizing it below:</p>
<ol>
<li><strong>Performance gains can hide chatty apps</strong><br />
A competent DBA will tell you they don’t want chatty apps that continually pound their database with small queries. This design pattern has the potential to hide such problems by the sheer increase in performance that it grants by reducing the number of database connections to one. I would emphasize that you not rely on this design pattern as a foundation for your application’s data tier performance, and instead make sure you don’t have chatty apps before “turning it on,” so to speak. Ensure that in the absence of this design pattern your application still performs at an acceptable level.</li>
<li><strong>Difficult or Time Consuming to Retrofit into Legacy Applications</strong><br />
If you are examining an existing system or application and you would like to find a way to apply this design pattern, but the system in question does not currently have well organized code for its data access tier, you may find yourself in a sinkhole of time. I am sure you would love to spend all the time in the world honing your data access tier to the Nth degree, but some older application that were not architected properly (or at all) can not only prove difficult to retrofit with this design pattern but, at the very least, very time consuming. If you are in a crunch for time, this may not be the best option if you are looking for performance gains with your data tier.</li>
<li><strong>Table Locking Issues</strong><br />
Depending on the isolation level chosen for your transaction, you have the potential to cause locking issues with the back-end database. Long running transactions can adversely affect the performance of other users running queries on the same table, so you need to make sure your application minimizes the amount of time it maintains the transaction.</li>
</ol>
<h2>Sample Code</h2>
<p>I am going to present sample code using a web application for ASP.NET in C#, but it can easily be converted into VB.NET. In an effort to make this example as portable as possible without any configuration changes on the part of the person downloading the sample, I will also utilize an Access Database. I will program to an interface, so switching out the data provider from Jet to SQL will be trivial.</p>
<p>In the world of ASP.NET, this design pattern is best implemented using an HTTP module. This means you need only implement the <a href="http://msdn.microsoft.com/en-us/library/system.web.ihttpmodule.aspx">System.Web.IHttpModule</a> interface and define it in the appropriate location in your web.config file (//configuration/system.web/httpModules for IIS6 or //configuration/system.webServer/modules for IIS7). The HTTP module implementor is supported by a session manager class that allows thread-safe access to the connection and transaction, and both of them are usually implemented and visible only to the data tier of your application (assuming a 3-tier architecture).</p>
<h3>Session Manager</h3>
<p>The source code to the real workhorse behind this design pattern is the Session Module:</p>
<p><!-- code formatted by http://manoli.net/csharpformat/ --></p>
<pre class="csharpcode"><span class="kwrd">using</span> System;
<span class="kwrd">using</span> System.Collections.Generic;
<span class="kwrd">using</span> System.Text;

<span class="kwrd">namespace</span> CSharpOSIV
{
    <span class="rem">/// &lt;summary&gt;</span>
    <span class="rem">/// The main entry point for the Open Session In View Design Pattern that</span>
    <span class="rem">/// allows access to the current thread's connection and transaction objects</span>
    <span class="rem">/// &lt;/summary&gt;</span>
    <span class="rem">/// &lt;remarks&gt;</span>
    <span class="rem">/// An interesting characteristic of this class is that it exposes the connection</span>
    <span class="rem">/// and transaction objects that are specific to the current thread, but only a single</span>
    <span class="rem">/// instance of it is ever created, which follows the Singleton Design Pattern.</span>
    <span class="rem">/// &lt;/remarks&gt;</span>
    <span class="kwrd">public</span> <span class="kwrd">sealed</span> <span class="kwrd">class</span> SessionManager
    {
        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// The key used when storing the connection in web or call context</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">string</span> THREADCONNECTION_KEY = <span class="str">"THREADCONNECTION_KEY"</span>;

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// The key used when storing the transaction in the web or call context</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">string</span> THREADTRANSACTION_KEY = <span class="str">"THREADTRANSACTION_KEY"</span>;

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// This class is exposed as a singleton and this static variable contains the instance</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">private</span> <span class="kwrd">static</span> SessionManager _Instance = <span class="kwrd">null</span>;

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Private constructor so it can only be accessed with the singleton</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">private</span> SessionManager()
        {
            <span class="rem">// make sure the Session Module is registered in the web.config</span>
            MakeSureModuleIsInWebConfig();
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// This utility method will make sure that the web.config entry exists, which is required for this manager to function properly</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> MakeSureModuleIsInWebConfig()
        {
            <span class="rem">// we only check the web.config if we are within a web context</span>
            <span class="kwrd">if</span> (IsInWebContext)
            {
                <span class="kwrd">using</span> (var fileStream = System.IO.File.OpenRead(System.AppDomain.CurrentDomain.SetupInformation.ConfigurationFile))
                {
                    var doc = <span class="kwrd">new</span> System.Xml.XPath.XPathDocument(fileStream);
                    var nav = doc.CreateNavigator();

                    <span class="rem">// IIS6 and IIS7 store the HTTP Module sections in different locations so we need to check both</span>
                    <span class="kwrd">bool</span> foundForIis6 = ModuleExists(nav, <span class="str">"/configuration/system.web/httpModules/add/@type"</span>);
                    <span class="kwrd">bool</span> foundForIis7 = ModuleExists(nav, <span class="str">"/configuration/system.webServer/modules/add/@type"</span>);

                    <span class="kwrd">if</span> (!(foundForIis6 || foundForIis7))
                    {
                        <span class="rem">// The HTTP Modules section is either missing or does not have the SessionModule defined in its list</span>
                        <span class="kwrd">throw</span> <span class="kwrd">new</span> Exceptions.SessionModuleNotRegisteredException();
                    }
                }
            }
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// This utility method checks for a specific module in the specified location of the web.config file's HTTP Modules section</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="rem">/// &lt;param name="nav"&gt;The XPathNavigator that allows for navigation to the proper node&lt;/param&gt;</span>
        <span class="rem">/// &lt;param name="xpathToTypeAttribute"&gt;The path that should be checked&lt;/param&gt;</span>
        <span class="rem">/// &lt;returns&gt;&lt;/returns&gt;</span>
        <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">bool</span> ModuleExists(System.Xml.XPath.XPathNavigator nav, <span class="kwrd">string</span> xpathToTypeAttribute)
        {
            <span class="kwrd">bool</span> result = <span class="kwrd">false</span>;
            <span class="kwrd">foreach</span> (System.Xml.XPath.XPathNavigator node <span class="kwrd">in</span> nav.Select(xpathToTypeAttribute))
            {
                <span class="kwrd">string</span> sType = node.ToString();
                <span class="kwrd">if</span> (!String.IsNullOrEmpty(sType))
                {
                    Type t = System.Type.GetType(sType, <span class="kwrd">false</span>, <span class="kwrd">true</span>);
                    <span class="kwrd">if</span> (<span class="kwrd">typeof</span>(SessionModule).Equals(t))
                    {
                        result = <span class="kwrd">true</span>;
                        <span class="rem">// once we find the HTTP module we can cut out early</span>
                        <span class="kwrd">break</span>;
                    }
                }
            }
            <span class="kwrd">return</span> result;
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Expose a singleton for the session manager</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">public</span> <span class="kwrd">static</span> SessionManager Instance
        {
            get
            {
                <span class="kwrd">if</span> (_Instance == <span class="kwrd">null</span>)
                {
                    <span class="rem">// this string, which is defined as a constant, is already interned, </span>
                    <span class="rem">// which makes it a suitable object on which to lock with the monitor</span>
                    <span class="kwrd">lock</span> (THREADCONNECTION_KEY)
                    {
                        <span class="kwrd">if</span> (_Instance == <span class="kwrd">null</span>)
                        {
                            _Instance = <span class="kwrd">new</span> SessionManager();
                        }
                    }
                }
                <span class="kwrd">return</span> _Instance;
            }
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Is the current thread functioning within a web context?</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">bool</span> IsInWebContext
        {
            get { <span class="kwrd">return</span> System.Web.HttpContext.Current != <span class="kwrd">null</span>; }
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// The thread-specific connection for the current request</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">private</span> System.Data.IDbConnection ThreadConnection
        {
            get
            {
                <span class="kwrd">if</span> (IsInWebContext)
                {
                    <span class="kwrd">return</span> System.Web.HttpContext.Current.Items[THREADCONNECTION_KEY] <span class="kwrd">as</span> System.Data.IDbConnection;
                }
                <span class="kwrd">else</span>
                {
                    <span class="kwrd">return</span> ReadCallContext&lt;System.Data.IDbConnection&gt;(THREADCONNECTION_KEY);
                }
            }
            set
            {
                <span class="kwrd">if</span> (IsInWebContext)
                {
                    System.Web.HttpContext.Current.Items[THREADCONNECTION_KEY] = <span class="kwrd">value</span>;
                }
                <span class="kwrd">else</span>
                {
                    StoreInCallContext(THREADCONNECTION_KEY, <span class="kwrd">value</span>);
                }
            }
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// The thread-specific transaction for the current request</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">private</span> System.Data.IDbTransaction ThreadTransaction
        {
            get
            {
                <span class="kwrd">if</span> (IsInWebContext)
                {
                    <span class="kwrd">return</span> System.Web.HttpContext.Current.Items[THREADTRANSACTION_KEY] <span class="kwrd">as</span> System.Data.IDbTransaction;
                }
                <span class="kwrd">else</span>
                {
                    <span class="kwrd">return</span> ReadCallContext&lt;System.Data.IDbTransaction&gt;(THREADTRANSACTION_KEY);
                }
            }
            set
            {
                <span class="kwrd">if</span> (IsInWebContext)
                {
                    System.Web.HttpContext.Current.Items[THREADTRANSACTION_KEY] = <span class="kwrd">value</span>;
                }
                <span class="kwrd">else</span>
                {
                    StoreInCallContext(THREADTRANSACTION_KEY, <span class="kwrd">value</span>);
                }
            }
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Utility method that stores data into the call context dictionary</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="rem">/// &lt;remarks&gt;</span>
        <span class="rem">/// Call Context class cannot be referenced in a medium-trust environment so it is refactored </span>
        <span class="rem">/// to a different method to prevent the ThreadConnection and ThreadTransaction properties from</span>
        <span class="rem">/// throwing security exception.</span>
        <span class="rem">/// &lt;/remarks&gt;</span>
        <span class="rem">/// &lt;param name="key"&gt;The key into which the object should be stored in the call context&lt;/param&gt;</span>
        <span class="rem">/// &lt;param name="obj"&gt;The object to store into the call context&lt;/param&gt;</span>
        <span class="kwrd">private</span> <span class="kwrd">static</span> <span class="kwrd">void</span> StoreInCallContext(<span class="kwrd">string</span> key, <span class="kwrd">object</span> obj)
        {
            <span class="rem">// The following call requires higher permissions than those available in a medium-trust environment</span>
            <span class="rem">// so the compiler should not in-line it, but if it does just move this method to a utility project</span>
            System.Runtime.Remoting.Messaging.CallContext.SetData(key, obj);
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Utility method that retrieves data from the call context dictionary</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="rem">/// &lt;remarks&gt;</span>
        <span class="rem">/// Call Context class cannot be referenced in a medium-trust environment so it is refactored</span>
        <span class="rem">/// to a different method to prevent the ThreadConnection and ThreadTransaction properties from</span>
        <span class="rem">/// throwing a security exception.</span>
        <span class="rem">/// &lt;/remarks&gt;</span>
        <span class="rem">/// &lt;typeparam name="T"&gt;The type of object that will be returned&lt;/typeparam&gt;</span>
        <span class="rem">/// &lt;param name="key"&gt;The key into the dictionary from which you should read&lt;/param&gt;</span>
        <span class="rem">/// &lt;returns&gt;&lt;/returns&gt;</span>
        <span class="kwrd">private</span> <span class="kwrd">static</span> T ReadCallContext&lt;T&gt;(<span class="kwrd">string</span> key)
        {
            <span class="rem">// The following call requires higher permissions than those available in a medium-trust environment</span>
            <span class="rem">// so the compiler should not in-line it, but if it does just move this method to a utility project</span>
            <span class="kwrd">return</span> (T)System.Runtime.Remoting.Messaging.CallContext.GetData(key);
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Does the current thread have an open connection?</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">private</span> <span class="kwrd">bool</span> HasOpenConnection
        {
            get
            {
                <span class="kwrd">return</span> (<span class="kwrd">this</span>.ThreadConnection != <span class="kwrd">null</span> &amp;&amp;
                        <span class="kwrd">this</span>.ThreadConnection.State == System.Data.ConnectionState.Open);
            }
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Does the current thread have an open transaction?</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">private</span> <span class="kwrd">bool</span> HasOpenTransaction
        {
            get
            {
                <span class="kwrd">return</span> (<span class="kwrd">this</span>.ThreadTransaction != <span class="kwrd">null</span>);
            }
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Starts the transaction using the specified data provider</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">public</span> <span class="kwrd">void</span> StartTransaction()
        {
            <span class="kwrd">if</span> (!HasOpenConnection) OpenConnection();
            <span class="kwrd">if</span> (!HasOpenTransaction) OpenTransaction();
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Utility method that opens the connection to the database if one does not already exist</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">private</span> <span class="kwrd">void</span> OpenConnection()
        {
            System.Data.IDbConnection connection = ThreadConnection;

            <span class="kwrd">if</span> (connection == <span class="kwrd">null</span>)
            {
                <span class="rem">// TODO: Make this more abstract and configurable through the web.config entry</span>
                <span class="rem">// but for now this will suffice for demonstration purposes</span>
                connection = <span class="kwrd">new</span> System.Data.OleDb.OleDbConnection(System.Configuration.ConfigurationManager.ConnectionStrings[<span class="str">"JetDB_OSIV"</span>].
                    ConnectionString.Replace(<span class="str">"~"</span>, System.Web.HttpContext.Current.Server.MapPath(<span class="str">"~/"</span>)));
                connection.Open();
                <span class="rem">// encapsulate the connection object with the wrapper class, which protects certain methods from execution</span>
                connection = <span class="kwrd">new</span> Wrappers.ConnectionWrapper(connection);
                <span class="kwrd">this</span>.ThreadConnection = connection;
            }
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Utility method that starts the transaction with the database if one does not already exist</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">private</span> <span class="kwrd">void</span> OpenTransaction()
        {
            System.Data.IDbConnection conn = ThreadConnection;
            System.Data.IDbTransaction trans = ThreadTransaction;
            <span class="kwrd">if</span> (conn != <span class="kwrd">null</span> &amp;&amp; trans == <span class="kwrd">null</span>)
            {
                <span class="kwrd">if</span> (conn <span class="kwrd">is</span> Wrappers.ConnectionWrapper)
                {
                    trans = ((Wrappers.ConnectionWrapper)conn).ManualBeginTransaction();
                }
                <span class="kwrd">else</span>
                {
                    trans = conn.BeginTransaction();
                }
                ThreadTransaction = trans;
            }
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Commit the transaction and close the connection with the database</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">public</span> <span class="kwrd">void</span> CommitTransaction()
        {
            <span class="kwrd">if</span> (HasOpenTransaction) FlushTransaction();
            <span class="kwrd">if</span> (HasOpenConnection) CloseConnection();
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Executing the flush operation with the database using the current transaction</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">private</span> <span class="kwrd">void</span> FlushTransaction()
        {
            System.Data.IDbTransaction trans = ThreadTransaction;

            <span class="kwrd">if</span> (trans != <span class="kwrd">null</span>)
            {
                <span class="kwrd">try</span>
                {
                    <span class="kwrd">if</span> (trans <span class="kwrd">is</span> Wrappers.TransactionWrapper)
                    {
                        ((Wrappers.TransactionWrapper)trans).ManualCommit();
                    }
                    <span class="kwrd">else</span>
                    {
                        trans.Commit();
                    }
                }
                <span class="kwrd">catch</span> (System.Exception ex)
                {
                    <span class="kwrd">throw</span> <span class="kwrd">new</span> Exceptions.SessionTransactionException(ex);
                }
                <span class="kwrd">finally</span>
                {
                    <span class="kwrd">if</span> (trans <span class="kwrd">is</span> Wrappers.TransactionWrapper)
                    {
                        ((Wrappers.TransactionWrapper)trans).ManualDispose();
                    }
                    <span class="kwrd">else</span>
                    {
                        trans.Dispose();
                    }
                    ThreadTransaction = <span class="kwrd">null</span>;
                }
            }
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Closes the current connection to the database</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">private</span> <span class="kwrd">void</span> CloseConnection()
        {
            System.Data.IDbConnection conn = ThreadConnection;

            <span class="kwrd">if</span> (conn != <span class="kwrd">null</span>)
            {
                <span class="kwrd">try</span>
                {
                    <span class="kwrd">if</span> (conn <span class="kwrd">is</span> Wrappers.ConnectionWrapper)
                    {
                        ((Wrappers.ConnectionWrapper)conn).ManualClose();
                    }
                    <span class="kwrd">else</span>
                    {
                        conn.Close();
                    }
                }
                <span class="kwrd">catch</span> (System.Exception ex)
                {
                    <span class="kwrd">throw</span> <span class="kwrd">new</span> Exceptions.SessionConnectionException(ex);
                }
                <span class="kwrd">finally</span>
                {
                    <span class="kwrd">if</span> (conn <span class="kwrd">is</span> Wrappers.ConnectionWrapper)
                    {
                        ((Wrappers.ConnectionWrapper)conn).ManualDispose();
                    }
                    <span class="kwrd">else</span>
                    {
                        conn.Dispose();
                    }
                }
            }
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Rolls the current transaction back and closes the connection</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">public</span> <span class="kwrd">void</span> RollbackTransaction()
        {
            <span class="kwrd">if</span> (HasOpenTransaction) Rollback();
            <span class="kwrd">if</span> (HasOpenConnection) CloseConnection();
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Executes the rollback unit of work</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="kwrd">private</span> <span class="kwrd">void</span> Rollback()
        {
            System.Data.IDbTransaction trans = ThreadTransaction;

            <span class="kwrd">if</span> (trans != <span class="kwrd">null</span>)
            {
                <span class="kwrd">try</span>
                {
                    trans.Rollback();
                }
                <span class="kwrd">catch</span>
                {
                    <span class="rem">// ignore errors - in a production environment you would log this event</span>
                }
                <span class="kwrd">finally</span>
                {
                    <span class="kwrd">if</span> (trans <span class="kwrd">is</span> Wrappers.TransactionWrapper)
                    {
                        <span class="kwrd">try</span> { ((Wrappers.TransactionWrapper)trans).ManualDispose(); }
                        <span class="kwrd">catch</span> { }
                    }
                    <span class="kwrd">else</span>
                    {
                        <span class="kwrd">try</span> { trans.Dispose(); }
                        <span class="kwrd">catch</span> { }
                    }
                }
            }
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Retrieves the current thread's connection</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="rem">/// &lt;returns&gt;The connection object for the current thread&lt;/returns&gt;</span>
        <span class="kwrd">public</span> System.Data.IDbConnection GetConnection()
        {
            <span class="kwrd">return</span> <span class="kwrd">this</span>.ThreadConnection;
        }

        <span class="rem">/// &lt;summary&gt;</span>
        <span class="rem">/// Retrieves the current thread's transaction</span>
        <span class="rem">/// &lt;/summary&gt;</span>
        <span class="rem">/// &lt;returns&gt;The transaction object for the current thread&lt;/returns&gt;</span>
        <span class="kwrd">public</span> System.Data.IDbTransaction GetTransaction()
        {
            <span class="kwrd">return</span> <span class="kwrd">this</span>.ThreadTransaction;
        }

    }
}</pre>
<p>The session manager’s job is to store the connection and transaction objects safely for later retrieval by the rest of your data access tier. In ASP.NET, this is accomplished using the HTTP Items collection because it is unique to the thread currently being used to serve up the current request. You will also note that in the absence of this collection (i.e. an application context), it reverts to the use of the call context, which functions in a similar manner.</p>
<p>You may have a few questions about this code, and I will try to answer the most obvious ones below:</p>
<ol>
<li><strong>If the HTTP Items collection is only available in a web context, and the call context is available in both contexts, why not always use the call context?</strong><br />
The answer to this question is quite complex, but suffice it to say that within a web context the call context can “lose” the data you store in it, especially in high-traffic scenarios, which makes it an unreliable storage medium for these objects. Second, if you are using a web application that must function in a medium-trust environment, you will be unable to even reference the call context class, which requires greater permissions than those granted under that scenario. However, if you are functioning within an application context (there is not web-context to deal with), then you are free to use it safely just like the HTTP context because in such a scenario it does not suffer this issue.</p>
<p><strong>NOTE:</strong>Despite my admittedly vague explanation above as to why the web context HTTP items collection should be used instead of the Call Context, it should be noted that the HTTP Items collection is stored in the call context. I will leave the reason for this as an exercise for the reader (because I&#8217;m lazy and don&#8217;t feel like explaining it).</li>
<li><strong>Why doesn’t this fail when more than a single user is using the website?</strong><br />
The Session Manager class essentially converts a statically visible dictionary into an instance dictionary suitable for use by any thread serving up an HTTP request, which is why I think it is such a creative solution. The HTTP Items collection is specific to the current thread serving the HTTP request just like the Call Context is specific to the current application thread in a Win Forms application. This allows the whole class to be exposed as a singleton (minimizing overhead for the entire application) and allows the rest of your application the comfort of being completely oblivious to what is really happening. This is a great example of encapsulation doing exactly what it should be doing with something more complex than a simple getter/setter.</li>
<li><strong>Wait, couldn’t my code inadvertently close the connection or commit the transaction after getting it from the session manager?</strong><br />
The short answer to this question is yes. However, through a creative use of the IDbConnection, IDbTransaction, and IDbCommand interfaces, you can circumvent this problem. The sample code provided addresses this issue. The Session Module specifically checks for the wrapper types and calls non-interface defined methods to close and dispose of the managed objects. A further optimization is to expand the code so that a connection is never even opened to the database unless a command is actually executed, but the sample code provided does not address this scenario for brevity.</li>
</ol>
<h3>Session Module</h3>
<p>The controller behind this design pattern is the session module. It is this HTTP module that controls when the connection is created at the beginning of the request and when the transaction is committed at the end of it. It is also responsible for making sure the transaction is rolled back in a situation where an error occurs. The implementation of the Session Manager makes this class’s implementation fairly trivial, which you will notice in the sample code below:</p>
<pre class="csharpcode"><span class="kwrd">using</span> System;
<span class="kwrd">using</span> System.Collections.Generic;
<span class="kwrd">using</span> System.Linq;
<span class="kwrd">using</span> System.Text;

<span class="kwrd">namespace</span> CSharpOSIV
{
    <span class="rem">/// &lt;summary&gt;</span>
    <span class="rem">/// An HTTP Module that permits the use of an open session in view design</span>
    <span class="rem">/// pattern by starting the transaction at the beginning of the HTTP request</span>
    <span class="rem">/// and committing it to the database at the end of the request.</span>
    <span class="rem">/// &lt;/summary&gt;</span>
    <span class="kwrd">public</span> <span class="kwrd">sealed</span> <span class="kwrd">class</span> SessionModule : System.Web.IHttpModule
    {
        <span class="kwrd">void</span> System.Web.IHttpModule.Init(System.Web.HttpApplication context)
        {
            context.BeginRequest += <span class="kwrd">new</span> EventHandler(context_BeginRequest);
            context.EndRequest += <span class="kwrd">new</span> EventHandler(context_EndRequest);
        }

        <span class="kwrd">void</span> context_BeginRequest(<span class="kwrd">object</span> sender, EventArgs e)
        {
            SessionManager.Instance.StartTransaction();
        }

        <span class="kwrd">void</span> context_EndRequest(<span class="kwrd">object</span> sender, EventArgs e)
        {
            <span class="kwrd">try</span>
            {
                SessionManager.Instance.CommitTransaction();
            }
            <span class="kwrd">catch</span>
            {
                SessionManager.Instance.RollbackTransaction();
            }
        }

        <span class="kwrd">void</span> System.Web.IHttpModule.Dispose()
        {
            <span class="rem">/* nothing to do */</span>
        }

    }
}</pre>
<p>The basic premise is that this module starts the database connection and transaction and cleans it up after the web request is finished. All of the necessary methods are present on the Session Manager.</p>
<h2>Other Considerations</h2>
<p>A few more points of interest regarding this design pattern include, but are not limited to, the following topics:</p>
<ol>
<li><strong>Impact of Connection Pooling</strong>
<p>The data provider for your database can usually be configured to use connection pooling (even Access Databases can do this, see the following link: <a href="http://msdn.microsoft.com/en-us/library/ms724518(VS.85).aspx)">http://msdn.microsoft.com/en-us/library/ms724518(VS.85).aspx</a>. Connection pooling is just another component for increasing performance in data-intensive web applications that complements, but does not make irrelevant, the design pattern discussed here.</p>
</li>
<li><strong>Read-Only Transactions</strong>
<p>Depending on the application, you may be able to further increase performance by fine tuning the isolation specified in your ASP.NET application by choosing the appropriate isolation level. Again, this depends entirely on the application, critical nature of the data, and concurrency issues, but using read-only transactions has the potential to further increase the performance of your database connection. The ability to apply this principle, however, may be nearly impossible in a real environment due to the inability to detect what types of queries are going to be executed (the sample project suffers from this problem so no isolation level is even specified).</p>
</li>
</ol>
<p>I could continue rambling on about the merits of this design pattern and its applications forever, but I will allow the sample solution file to speak for itself. I believe the information presented above and in the sample project file should give a good primer the Open Session In View design pattern. I look forward to hearing feedback and comments regarding the sample code and thoughts and suggestions about ways it can be improved.</p>
<h2>Credits</h2>
<p>I would like to make sure I give credit to others who inspired me to create the solution that is attached to this blog entry. I didn&#8217;t come up with most of the concepts completely on my own, but I did build on them quite a bit.</p>
<p><a href="http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx">http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx</a><br />
<a href="https://www.hibernate.org/43.html">https://www.hibernate.org/43.html</a></p>
<h2>License</h2>
<p>This source code is licensed under the <a href="http://www.gnu.org/licenses/lgpl.txt">GNU Lesser General Public License</a>. I would appreciate credit if you use this source code as a base for any implementation and would especially love to know where it has been applied!</p>
<h2>Sample Project Download</h2>
<p>You can download the sample project by clicking on the following link: <a href="http://www.cirrusabs.com/document-download.aspx/open-session-in-view-design-pattern">Download ZIP of Solution</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cirrusabs.com/blog/application-performance-open-session-in-view-design-pattern/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
