<?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>Jonathan Stowell</title>
	<atom:link href="http://jonathanstowell.com/blog/index.php/feed" rel="self" type="application/rss+xml" />
	<link>http://jonathanstowell.com/blog</link>
	<description>Bsc(Hons) Computing</description>
	<lastBuildDate>Mon, 09 Jan 2012 21:44:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>My Application Framework &#8211; Part 5 &#8211; Pre-compiled Views</title>
		<link>http://jonathanstowell.com/blog/index.php/asp-net-mvc/my-application-framework-part-5-pre-compiled-views</link>
		<comments>http://jonathanstowell.com/blog/index.php/asp-net-mvc/my-application-framework-part-5-pre-compiled-views#comments</comments>
		<pubDate>Mon, 09 Jan 2012 21:39:26 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
				<category><![CDATA[ASP.NET MVC]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[My Framework]]></category>

		<guid isPermaLink="false">http://jonathanstowell.com/blog/?p=463</guid>
		<description><![CDATA[So whilst I was trying to get up to speed at work and working out how a plugin based system could work. I started to think about the best way to manage my pages. I thought it would be pretty cool if you could compile them into the frontend library. After some research I came [...]]]></description>
			<content:encoded><![CDATA[<p>So whilst I was trying to get up to speed at work and working out how a plugin based system could work. I started to think about the best way to manage my pages. I thought it would be pretty cool if you could compile them into the frontend library. After some research I came across <a href="http://blog.davidebbo.com/2011/06/precompile-your-mvc-views-using.html" title="RazorGenerator">David Ebbo&#8217;s RazorGenerator</a>. </p>
<p>I decided to use this and decided to load all of my pages into Windsor on start-up and then pass them into a View Engine that I would write loosely based upon one I found whilst researching David&#8217;s implementation. It was quite simple in the end. I simply passed the Windsor container into my View Engine.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">private readonly IWindsorContainer _container;<br />
<br />
public WindsorPrecompiledViewEngine(IWindsorContainer container)<br />
{<br />
&nbsp; &nbsp; &nbsp;_container = container;<br />
}</div></td></tr></tbody></table></div>
<p>Then when a page is requested:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)<br />
{<br />
&nbsp; &nbsp; &nbsp;string key = GetKey(partialPath, IsMobile(controllerContext));<br />
&nbsp; &nbsp; &nbsp;WebViewPage type = _container.Kernel.Resolve&lt;WebViewPage&gt;(key);<br />
&nbsp; &nbsp; &nbsp;if (type != null)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new PrecompiledView(partialPath, type, false, FileExtensions);<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;return null;<br />
}<br />
<br />
protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)<br />
{<br />
&nbsp; &nbsp; &nbsp;WebViewPage type;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp;try<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type = _container.Kernel.Resolve&lt;WebViewPage&gt;(GetKey(viewPath, IsMobile(controllerContext)));<br />
&nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp;catch (Exception)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type = null;<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;if (type != null)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new PrecompiledView(viewPath, type, true, FileExtensions);<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;return null;<br />
}</div></td></tr></tbody></table></div>
<p>The code simply works out the string of the key that would have been used when the view was registered in the container. It also checks to see whether the HTTP Request came from a Mobile Device using an extension method I wrote. If so it formats the key to look for a mobile view. This was an idea I has as I thought it would be pretty cool to use jQuery Mobile to create a mobile version of pages. However this is a future idea really as it&#8217;s not worth putting the time into at the moment. Finally if it finds the view it returns it as a Pre-compiled View Object which I believe was taken from David&#8217;s example.</p>
<p>This is all plugged in as a Bootstrapping task which adds this View Engine to MVC:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class PrecompiledViewEngineStartupTask : IStartupTask<br />
{<br />
&nbsp; &nbsp; &nbsp;public void Run()<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var engine = new WindsorPrecompiledViewEngine((IWindsorContainer)Bootstrapper.Container);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ViewEngines.Engines.Add(engine);<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;public void Reset()<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new NotImplementedException();<br />
&nbsp; &nbsp; &nbsp;}<br />
}</div></td></tr></tbody></table></div>
<p>Future ideas for this evolve around changing views without having to restart the web server. At the moment if you want to change a page you have to deploy the front end library and restart the server. I came across this <a href="http://ayende.com/blog/2792/introducing-monorail-hotswap" title="Hot Swapping">Hot Swapping concept from Ayende Rahien</a> and believe it would be possible to do this for swapping out old views for new views in the Windsor container. This could also be possible for any of the libraries dropped into the Plugin folder and could be an interesting feature to work on in the future.</p>
<p>Anyway hope this was interesting!</p>
]]></content:encoded>
			<wfw:commentRss>http://jonathanstowell.com/blog/index.php/asp-net-mvc/my-application-framework-part-5-pre-compiled-views/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My Application Framework &#8211; Part Four &#8211; Brief SOA / Route Registration / Navigation</title>
		<link>http://jonathanstowell.com/blog/index.php/asp-net-mvc/my-application-framework-part-four-brief-soa-route-registration-navigation</link>
		<comments>http://jonathanstowell.com/blog/index.php/asp-net-mvc/my-application-framework-part-four-brief-soa-route-registration-navigation#comments</comments>
		<pubDate>Mon, 09 Jan 2012 13:33:00 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
				<category><![CDATA[ASP.NET MVC]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[My Framework]]></category>

		<guid isPermaLink="false">http://jonathanstowell.com/blog/?p=436</guid>
		<description><![CDATA[Brief SOA Front end project can register routes and their navigation structures. The reason I like to register routes is due to the way of working I have undertaken since starting my new job. My new work use a Service Orientated Architecture. They have begun to break down their application into services made up of [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Brief SOA</strong></p>
<p>Front end project can register routes and their navigation structures. The reason I like to register routes is due to the way of working I have undertaken since starting my new job. My new work use a Service Orientated Architecture. They have begun to break down their application into services made up of autonomous components. The components should be able to act independently but can work together by using messaging. Each component has its own entities, own entities, own front-end, own back-end etc.</p>
<p>It works by processing user input validating it, returning errors to the user or sending a message off to the bus. An action which is initiated by a component and processed by the components back-end is called a Command Message. Once processed by the message handler an Event Message is sent out to notify the other components.</p>
<p>Now I have an external message library which form the basis of these event messages allowing applications external to my service to listen to the queue and process any information they may need from certain events occurring. These external messages are extended by internal messages which are use by components inside the service and which may contain more sensitive information than what external sources may be allowed to see.</p>
<p>As in my case each component supplies its own nHibernate session which is built using the components fluent mappings. This should technically allow for your application to be distributed across many computers if demand requires it to be. It should allow it scale a lot more simply than the way traditional systems are built, by just deploying components or services to individual servers and setting them up to send messages to the relevant message queues.</p>
<p>As each component has its own entities and its own set of database tables it should be possible to “shard” the database and distribute it across many computers with no need for it to be in a cluster. Also I’m no expert on this but listening to conversations at work it should be possible to use load balancer’s to forward messages on to many computers running the same service or component. If a component is under strain you should just be able to add another server, setup a service host, listen to the message queues and away you go, you can now satisfy more demand on the popular parts of your system. Again don’t quote me on this, I’m young and still have a long way to go, but it sounds like a brilliant idea to me!</p>
<p><strong>Routes</strong></p>
<p>This basically forms my arguments for each front-end plug-in registering routes. As each autonomous component should be able to act independently, but each component has a slight coupling with the other components in its service. It should hide the concrete routes from any component or service which wishes to access what it offers. This way if you wanted to replace a component you could use the same registered routes and just point them to the new concrete routes in your new plug-in. I have managed to do this for web requests initialised by the user but not when I attempt to pull components into a host component using RenderAction. RenderAction does not seem to process the request through the routing engine so I get an issue in the Windsor Controller Factory. If anyone knows more about this process it would be good if you could get in contact with me and give me some advice on this one.</p>
<p>A Route Registration appears like this:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class RegisterRoutes : IRegisterRoutes<br />
{<br />
&nbsp; &nbsp; &nbsp;public void Register(RouteCollection routes)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; routes.MapRoute(<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;RoleCreate&quot;,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&quot;Role/Create&quot;,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new { controller = &quot;RoleManagement&quot;, action = &quot;Create&quot; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; );<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; routes.MapRoute(<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot;RoleEdit&quot;,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot;Role/Edit/{id}&quot;,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;new { controller = &quot;RoleManagement&quot;, action = &quot;Edit&quot;, id = &quot;&quot; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; );<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; routes.MapRoute(<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot;RoleRename&quot;,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot;Role/Rename/{id}/{name}&quot;,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;new { controller = &quot;RoleManagement&quot;, action = &quot;Edit&quot;, id = &quot;&quot;, name = &quot;&quot; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; );<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; routes.MapRoute(<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot;RoleDelete&quot;,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &quot;Role/Delete/{id}&quot;,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;new { controller = &quot;RoleManagement&quot;, action = &quot;Delete&quot;, id = &quot;&quot; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; );<br />
&nbsp; &nbsp; &nbsp;}<br />
}</div></td></tr></tbody></table></div>
<p>A class simply implements the IRegisterRoutes interface and register routes as if it would in the Global.asax. Then on start-up these classes are resolved from Windsor and executed passing in the RouteTable.</p>
<p><strong>Navigation</strong></p>
<p>Front end libraries can also register their navigation:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class RegisterNavigation : IRegisterNavigation<br />
{<br />
&nbsp; &nbsp; &nbsp;public NavigationNode Path<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;NavigationNode host = new NavigationNode<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Action = &quot;Index&quot;,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Controller = &quot;UserHost&quot;,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Name = &quot;User System&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;};<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;NavigationNode roles = new NavigationNode<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Controller = &quot;Roles&quot;,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Name = &quot;Role Management&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;};<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;host.Children.Add(roles);<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return host;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;public string[] Roles<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get { return new[] { &quot;Creator&quot;, &quot;Admin&quot;, &quot;UserAccess&quot; }; }<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;public bool RequireAllRoles<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get { return false; }<br />
&nbsp; &nbsp; &nbsp;}<br />
}</div></td></tr></tbody></table></div>
<p>This defines a tree structure of Navigation Nodes which include the details to create the navigation links, and the security information to access the part of the system.</p>
<p>All of these navigation registrations are passed into a class which creates a navigation tree on start-up. This class is used by the navigation controller to render the navigation for each user. Upon request the class loops over each registration and adds it to a navigation data structure if the user is privileged enough to access the part of the system the registration describes.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public DataStructures.Navigation GetNavigation(ThreeBytesPrincipal principal)<br />
{<br />
&nbsp; &nbsp; &nbsp;var result = new DataStructures.Navigation();<br />
<br />
&nbsp; &nbsp; &nbsp;foreach (var nav in container.ResolveAll&lt;IRegisterNavigation&gt;().OrderBy(x =&gt; x.Path.Name))<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (nav.Roles.Length &gt; 0)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (principal != null)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (nav.RequireAllRoles)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (!principal.IsInAnyRoles(nav.Roles))<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; continue;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (!principal.IsInAnyRoles(nav.Roles))<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;continue;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result.Add(nav);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;result.Add(nav);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;return result;<br />
}</div></td></tr></tbody></table></div>
<p>The Navigation Data Structure recursively loops over the path supplied by the registration adding it to a Navigation Nodes list, merging nodes of the same path until they differ.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class Navigation<br />
{<br />
&nbsp; &nbsp; &nbsp;public IList&lt;NavigationNode&gt; NavigationNodes { get; set; }<br />
<br />
&nbsp; &nbsp; &nbsp;public Navigation()<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NavigationNodes = new List&lt;NavigationNode&gt;();<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;public void Add(IRegisterNavigation navigation)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AddInternal(navigation.Path);<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;private void AddInternal(NavigationNode path)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AddRecursive(NavigationNodes, path);<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;private void AddRecursive(IList&lt;NavigationNode&gt; navigationNodes, NavigationNode toAdd)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (navigationNodes.Contains(toAdd))<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;foreach (var node in toAdd.Children)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;AddRecursive(navigationNodes.Single(x =&gt; x.Name == toAdd.Name).Children, node);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;navigationNodes.Add(toAdd);<br />
&nbsp; &nbsp; &nbsp;}<br />
}</div></td></tr></tbody></table></div>
<p>I then have a HTML Helper which outputs the relevant HTML to complement the structure built by this class.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonathanstowell.com/blog/index.php/asp-net-mvc/my-application-framework-part-four-brief-soa-route-registration-navigation/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My Application Framework &#8211; Part Three &#8211; Windsor Registration and it’s role in Plug-ins</title>
		<link>http://jonathanstowell.com/blog/index.php/asp-net-mvc/my-application-framework-part-three-windsor-registration-and-its-role-in-plug-ins</link>
		<comments>http://jonathanstowell.com/blog/index.php/asp-net-mvc/my-application-framework-part-three-windsor-registration-and-its-role-in-plug-ins#comments</comments>
		<pubDate>Mon, 09 Jan 2012 13:29:52 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
				<category><![CDATA[ASP.NET MVC]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[My Framework]]></category>
		<category><![CDATA[Windsor]]></category>

		<guid isPermaLink="false">http://jonathanstowell.com/blog/?p=434</guid>
		<description><![CDATA[I previously mentioned the bootstrapping task registering everything in classes which implement IWebWindsorRegistration and IBusWindsorRegistration. The way I structure my applications is to have a library of interfaces which perform a specific task and then a library of concrete implementations of those interfaces. For example I divide my application up into Data classes which use [...]]]></description>
			<content:encoded><![CDATA[<p>I previously mentioned the bootstrapping task registering everything in classes which implement IWebWindsorRegistration and IBusWindsorRegistration. The way I structure my applications is to have a library of interfaces which perform a specific task and then a library of concrete implementations of those interfaces.</p>
<p>For example I divide my application up into Data classes which use generic repositories to provide data access via nHibernate. Service classes which provide a caching layer on top of these repositories. Validation libraries which provided validation for the Domain Objects. Frontend libraries which consume the services and provide a means to handle web requests, serve pages and fire off messages for the Backend Message Handlers to process. I will get into this in a later article in more detail.</p>
<p>However each concrete library has an Installers folder which contains a class which implements IWebWindsorRegistration and IBusWindsorRegistration and may include something like this:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public void Install(IWindsorContainer container)<br />
{<br />
&nbsp; &nbsp; &nbsp;container.Register(<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AllTypes.FromThisAssembly().BasedOn&lt;IRoleManagementRoleDatabaseFactory&gt;().Configure(<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;component =&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; component.Named(component.Implementation.Name);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; component.LifeStyle.Is(LifestyleType.PerWebRequest);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}).WithService.Base(),<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AllTypes.FromThisAssembly().BasedOn&lt;IRoleManagementRoleUnitOfWork&gt;().Configure(<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;component =&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; component.Named(component.Implementation.Name);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; component.LifeStyle.Is(LifestyleType.PerWebRequest);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}).WithService.Base(),<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AllTypes.FromThisAssembly().BasedOn&lt;IRoleManagementRoleRepository&gt;().Configure(<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;component =&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;component.Named(component.Implementation.Name);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;component.LifeStyle.Is(LifestyleType.PerWebRequest);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}).WithService.Base()<br />
&nbsp; &nbsp; &nbsp;);<br />
}</div></td></tr></tbody></table></div>
<p>Upon start-up the Windsor Bootstrapper extension executes all of these classes and installs the dependencies into the container. So we have libraries being installed from outside of the bin directory into the container for our application to serve up.</p>
<p>The way this works in the context of serving up content is as so:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public void Install(IWindsorContainer container)<br />
{<br />
&nbsp; &nbsp; &nbsp;container.Register(<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AllTypes.FromThisAssembly().BasedOn&lt;IController&gt;().Configure(<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;component =&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; component.Named(component.Implementation.Name);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; component.LifeStyle.Is(LifestyleType.Transient);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}).WithService.Base(),<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AllTypes.FromThisAssembly().BasedOn&lt;WebViewPage&gt;().Configure(<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;component =&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;component.Named(ViewKeyGenerator.GetViewKey(component.Implementation.FullName));<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}).WithService.Base(),<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AllTypes.FromThisAssembly().BasedOn&lt;IRegisterRoutes&gt;().Unless(x =&gt; x.IsAbstract).Configure(x =&gt; x.LifeStyle.Singleton),<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AllTypes.FromThisAssembly().BasedOn&lt;IRegisterNavigation&gt;().Unless(x =&gt; x.IsAbstract).Configure(x =&gt; x.LifeStyle.Singleton),<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AllTypes.FromThisAssembly().BasedOn&lt;ICommand&gt;().Unless(x =&gt; x.IsAbstract).Configure(x =&gt; x.LifeStyle.Transient)<br />
&nbsp; &nbsp; &nbsp;);<br />
&nbsp;}</div></td></tr></tbody></table></div>
<p>Each frontend project registers all of its controllers, all of its Web Pages using a method I wrote to format it’s implementation name, all of its route registrations, all of its navigation registrations and finally all of its commands that it uses to process user input, ensure its valid before sending a message off to the Bus.</p>
<p>With everything in the container when a request for a controller comes in the Windsor Controller Factory resolves it from the container. When the controller returns its page the page is found in the container and rendered as the result of the request.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonathanstowell.com/blog/index.php/asp-net-mvc/my-application-framework-part-three-windsor-registration-and-its-role-in-plug-ins/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My Application Framework &#8211; Part Two &#8211; Assembly Resolve</title>
		<link>http://jonathanstowell.com/blog/index.php/asp-net-mvc/my-application-framework-part-two-assembly-resolve</link>
		<comments>http://jonathanstowell.com/blog/index.php/asp-net-mvc/my-application-framework-part-two-assembly-resolve#comments</comments>
		<pubDate>Mon, 09 Jan 2012 13:27:25 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
				<category><![CDATA[ASP.NET MVC]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[My Framework]]></category>

		<guid isPermaLink="false">http://jonathanstowell.com/blog/?p=430</guid>
		<description><![CDATA[In order to use code which exists outside the bin directory we must write a class that loads these assemblies using reflection and finds these assemblies when the system requires them. The ResolveAssemblies class scans a supplied directory for libraries matching supplied patterns. In my case it scans a Plugins folder for assemblies that begin [...]]]></description>
			<content:encoded><![CDATA[<div>In order to use code which exists outside the bin directory we must write a class that loads these assemblies using reflection and finds these assemblies when the system requires them.</p>
<p>The ResolveAssemblies class scans a supplied directory for libraries matching supplied patterns. In my case it scans a Plugins folder for assemblies that begin with ThreeBytes.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">var scanPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, path);<br />
var directory = new DirectoryInfo(scanPath);<br />
var files = new HashSet&lt;FileInfo&gt;();<br />
try<br />
{<br />
&nbsp; &nbsp; &nbsp;foreach (var pattern in patterns)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var found = directory.GetFiles(pattern, SearchOption.AllDirectories);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; files.UnionWith(found);<br />
&nbsp; &nbsp; &nbsp;}<br />
}<br />
catch (Exception)<br />
{ }</div></td></tr></tbody></table></div>
<p>It then attempts to load these assemblies and then register them in a dictionary.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">foreach (var file in files)<br />
{<br />
&nbsp; &nbsp; &nbsp;var assembly = Assembly.LoadFrom(file.FullName);<br />
&nbsp; &nbsp; &nbsp;assembly.GetTypes();<br />
&nbsp; &nbsp; &nbsp;RegisterAssembly(assembly.FullName, assembly);<br />
}<br />
<br />
private void RegisterAssembly(string assemblyName, Assembly assembly)<br />
{<br />
&nbsp; &nbsp; &nbsp;var comma = assemblyName.IndexOf(',');<br />
&nbsp; &nbsp; &nbsp;pluginAssembliesByFullName[assemblyName] = assembly;<br />
&nbsp; &nbsp; &nbsp;pluginAssembliesByFullName[comma == -1 ? assemblyName : assemblyName.Substring(0, comma)] = assembly;<br />
}</div></td></tr></tbody></table></div>
<p>Finally our <a href="http://jonathanstowell.com/blog/index.php/asp-net-mvc/my-application-framework-part-one-startup" title="My Application Framework – Part One – Startup">start-up task</a> adds this method when the system needs to find an assembly.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">private bool TryGetAssembly(string assemblyName, out Assembly assembly)&lt;/p&gt;<br />
{<br />
&nbsp; &nbsp; &nbsp;return PluginAssembliesByFullName.TryGetValue(assemblyName, out assembly);<br />
}</div></td></tr></tbody></table></div>
<p>Which simply looks in the dictionary for the assembly the system is looking for.</p></div>
]]></content:encoded>
			<wfw:commentRss>http://jonathanstowell.com/blog/index.php/asp-net-mvc/my-application-framework-part-two-assembly-resolve/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My Application Framework &#8211; Part One &#8211; Startup</title>
		<link>http://jonathanstowell.com/blog/index.php/asp-net-mvc/my-application-framework-part-one-startup</link>
		<comments>http://jonathanstowell.com/blog/index.php/asp-net-mvc/my-application-framework-part-one-startup#comments</comments>
		<pubDate>Mon, 09 Jan 2012 13:23:34 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
				<category><![CDATA[ASP.NET MVC]]></category>
		<category><![CDATA[Bootstrapping]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[My Framework]]></category>

		<guid isPermaLink="false">http://jonathanstowell.com/blog/?p=421</guid>
		<description><![CDATA[When one of my websites or service hosts starts up it executes a series of start-up tasks to prime the application for run time. I discovered this great bootstrapping library on codeplex, cleverly named bootstrapper written by luisbocaletti. Using this framework you can create several classes that implement IStartupTask which will execute on start-up, as [...]]]></description>
			<content:encoded><![CDATA[<p>When one of my websites or service hosts starts up it executes a series of start-up tasks to prime the application for run time. I discovered this great bootstrapping library on codeplex, cleverly named bootstrapper written by luisbocaletti. Using this framework you can create several classes that implement IStartupTask which will execute on start-up, as long as you include the bootstrapper initialisation code.</p>
<p>You can also write dependency injection container extensions for it to install your dependencies into a container of your choice on start-up. I based my Windsor extension on the one I found on the Bootstrapper website. However I customised it to my needs. I have customised it to take an environment setting which will then set the context of whether the bootstrap operation is occurring for a web based system or a bus based system. It also takes the class I wrote to store assemblies that are not stored in the bin directory (this will be explained in a later article).</p>
<p>Upon execution of the first part of the bootstrapping initialisation:</p>
<p style="padding-left: 30px;">
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Bootstrapper.With.Windsor(AssemblyResolver, BootstrapEnvironment.WEB)</div></td></tr></tbody></table></div>
</p>
<p>The code registers every class that implements an IRegister interface into the container. Then depending on the context it runs every class that registers dependencies into Windsor. In the case of the Web it executes every Register(IWindsorContainer container) for every class that implements IWebWindsorRegistration, in the case of the service host it executes every IBusWindsorRegistration.</p>
<p>This allows one to specify different lifestyles for different dependencies. For example in a web context you are likely to want to manage your data access classes on a per web request basis. However in a service host context you may want to specify a per thread lifestyle.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Bootstrapper.With.Windsor(AssemblyResolver, BootstrapEnvironment.WEB).And.StartupTasks()<br />
&nbsp; &nbsp; &nbsp;.UsingThisExecutionOrder(s =&gt; s<br />
&nbsp; &nbsp; &nbsp;.First()<br />
&nbsp; &nbsp; &nbsp;.Then()<br />
&nbsp; &nbsp; &nbsp;.Then().TheRest())<br />
&nbsp; &nbsp; &nbsp;.Start();</div></td></tr></tbody></table></div>
<p>Once registering everything into the container the bootstrapper begins the start-up tasks. Beginning with adding a method to the app domain assembly resolve method which points to the GetAssembly method in the class I have to manage assemblies which are loaded from outside the bin folder. Now when an assembly is required it will also execute this method and return the assembly if it is located within the dictionary where the external libraries are loaded.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public void Run()<br />
{<br />
&nbsp; &nbsp; &nbsp;AppDomain.CurrentDomain.AssemblyResolve += (a, args) =&amp;gt; MvcApplication.AssemblyResolver.GetAssembly(args.Name);<br />
}</div></td></tr></tbody></table></div>
<p>The bootstrapper then executes the start-up task to configure nServiceBus allowing messages to be sent from the website to a configured MSMQ queue and picked up by the service host (Will be covered by a later article).</p>
<p>There are then a series of other start-up tasks. I have used Fluent Validation on this project as I found the Data Annotations framework quite limiting. There are going to be regular situations where you want more than simple validation and you need to validate against a database. For example when a register attempts to create an account, does a user with their details already exists? As Data Annotations use filters it is not possible to inject a repository or nHibernate session into the filter and validate against a database. Fluent Validation however does allow you to and I believe it still creates unobtrusive javascript for the simple validation rules. Anyway one of the start up tasks for the web context adds a new Validation Provider to the ModelValdationProviders class. All validations are also installed into my Windsor Container using my Windsor Installers allowing them to be injected into any class.</p>
<p>There is also a Logging Start-up Task which registers a global filter I wrote to handle errors. If an exception is unhanded it sends a message to the logging queue for the logging system to process.</p>
<p>There is the standard overriding of the controller factory to resolve controllers from the Windsor container. This works nicely with the plug-in approach I will explain in later articles as with my IWebWindsorInstallers you can register the controllers you create in the plug-ins into the container which are loaded from outside the bin directory.</p>
<p>There is a task to register routes into the routing table. Routes can be registered by the plug-in libraries by implementing an IRegisterRoutes interface I have created and installing them into the container using the previously mentioned IWebWindsorInstaller. The start-up task resolves all of the classes which implement IRegisterRoutes and registers all the defined routes into the route table.</p>
<p>There are two more tasks for the process of starting the Web Application. The penultimate one is adding a view engine to the MVC Framework. The view engine allows the system to return razor views which have been registered into the Windsor Container. Using David Ebbo’s Razor Generator each plug-in compiles their views which are then registered into the container during the install tasks. Then upon each request the view is searched for in the container before looking in the standard file disk locations.</p>
<p>The final task creates a navigation structure. Each plug-in can register a navigation structure in the form of a tree structure. They can define things such as the roles required to access that component. Upon start-up the container is passed to a class which upon each requests outputs a navigation structure using the navigation information provided by each plug-in. Obviously it does not include paths which the current user does not have access rights for. It does however merge paths of the same structure until they differ, for example on the final leaf node.</p>
<p>Now some of you maybe here thinking, he’s talked a lot about the Web Context but what about the Service Host. Where did that go? The service host also uses the bootstrapper and installs all the classes that implement IBusWindsorInstaller. However it only really has the start-up task to resolve assemblies from outside of the bin directory.</p>
<p>Apologies for quickly brushing over the tasks. I have done so as they pretty much each deserve their own article, hence the part one. These will be coming in the forthcoming weeks however for now I just wanted to make a start and where better than how it starts up. Hopefully how things work will become clearer as I begin to write about how all of these pieces slot together.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonathanstowell.com/blog/index.php/asp-net-mvc/my-application-framework-part-one-startup/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My Application Framework</title>
		<link>http://jonathanstowell.com/blog/index.php/asp-net-mvc/my-application-framework</link>
		<comments>http://jonathanstowell.com/blog/index.php/asp-net-mvc/my-application-framework#comments</comments>
		<pubDate>Thu, 29 Dec 2011 20:00:01 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
				<category><![CDATA[ASP.NET MVC]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[My Framework]]></category>

		<guid isPermaLink="false">http://jonathanstowell.com/blog/?p=410</guid>
		<description><![CDATA[Going to try and keep this one short as I don&#8217;t want to bore anyone! About six months ago now I began attempting to create my own framework of systems that I could use when building websites. My vision was to have a core set of libraries that could be used across any system for [...]]]></description>
			<content:encoded><![CDATA[<p>Going to try and keep this one short as I don&#8217;t want to bore anyone!</p>
<p>About six months ago now I began attempting to create my own framework of systems that I could use when building websites. My vision was to have a core set of libraries that could be used across any system for example I have Generic Repositories which allow data access for any entity that implements my IBusinessObject interface. I also have a set of Generic Service classes for my Business Objects which in time will hopefully act as a Caching layer when I get time to write a Memcached implementation. I also wanted to have a User, Logging and Email system which could also be used by any application and which would use my core libraries.</p>
<p>Anyway I began creating this in a traditional way having a relational database etc etc, but then I got a new job with Illy Systems and met some extremely intelligent developers. This lead me to rethink my Framework and I began to work in a new way.</p>
<p>The guys at work had just started using nServiceBus in a &#8220;Pluggable&#8221; way. I found this really interesting and whilst they use monorail for their website frontend. I wanted to create a way to do it with ASP MVC.</p>
<p>So this is how I&#8217;ve done it. When the Web / Service Bus applications start up they scan a certain directory for assemblies. In the Web project it is {WebDir}/Plugins in the service bus this is located in the bin/Plugins. It loads all of these assemblies into a dictionary. Once complete the application executes a series of startup tasks starting with scanning all of the assemblies in the dictionary for Windsor Installers. I have two types of installers a IWebInstaller and IBusInstaller and you set the context upon calling the Bootstrapper in the Global.asax. This then installs everything you tell it to into the Windsor Container from the plugin assemblies.</p>
<p>This includes all Repositories, Services, Validations, Configuration, Controllers, Razor Views where I have used David Ebbo&#8217;s Razor Generator to compile them, and then two interfaces I have created call IRegisterRoutes and IRegisterNavigation (We shall get to these in a bit).</p>
<ul>
<li>It then adds a new method to the app domain assembly resolve event handler which exists in the class which contains the dictionary of assemblies. Now when the application needs an assembly it will check the dictionary as well as the bin folder/gac.</li>
</ul>
<ul>
<li>It then starts nServiceBus and registers it into the Windsor Container.</li>
</ul>
<ul>
<li>It then overrides the View Engine with one that looks in the Windsor Container for the page instead of on the file system.</li>
</ul>
<ul>
<li>It then overrides the Model Validation and uses the Fluent Validation framework instead.</li>
</ul>
<ul>
<li>It then initialises Logging using a Global Filter which will send a Message to the Logging queue for the logging service host to handle whenever there is an unhandled exception.</li>
</ul>
<ul>
<li>It then Resolves all of the IRegisterRoutes from the container and adds them to the Routes Table. I thought this could be a good idea for developing in a plugin / soa way as each of your components can consume other components and using routes can mask the actual implementation of these controllers, making it easier to swap in and out new plugins when needed. However I have only managed to get this to work when a request comes in from a browser. When I use ActionResult which I believe creates a new request but only in an internal way it doesn&#8217;t seem to use the routing engine (Help with this bit would be appreciated!)</li>
</ul>
<ul>
<li>It then also resolves all of the IRegisterNavigation implementations and builds an overall Navigation structure from them which is then registered into the container.</li>
<li>Finally it overrides the Controller Factory with one that resolves the controllers from Windsor.</li>
</ul>
<p>The application is being created in a way where you have Services which are made up of Autonomous Components which act independently of each but which share a set of messages in order to maintain their own datasets and perform what they need to do depending on the events which have happened in the system. Some of these messages inherit from an external source of messages which is information which is deemed to be ok to share with other services. These could be services you build or services someone else has built who doesn&#8217;t even know you. This makes it necessary to think about what you are exposing to the external world.</p>
<p>Basically in a normal process this is what happens. User performs an action using an interface. This gets mapped to a controller action which then populates a pre command. The pre command populates an object and validates it. If the object is not valid the controller returns the Validation Results from the pre command and validation messages are shown for the user to try again. On a valid attempt the pre command then sends a message on to the Bus and releases the request. The message sent is generally a command message which is handled by one backend message handler. The handler validates the process again and ensures its still ok to complete this action. If it isn&#8217;t it throws an exception, if it is it persists the action and then publishes an event message. It&#8217;s this event message that other components listen to. As the internal messages inherit from the external messages. Other messages in the same service can get the extra information exposed to them and external components still receive the messages with less information exposed to them. These handlers then perform whatever they need to do.</p>
<p>Once complete the front end is now up to date with the backend but the user hasn&#8217;t had to wait for the process to complete.</p>
<p>The reason for developing in this way is to create a system that can easily be distributed and hence allow it to scale (This is perhaps for another article or your own reading).</p>
<p>Obviously the user is going to experience an out of sync system. However I have a few ideas on how caching could be used to &#8220;fake&#8221; their actions and make it appear to be completed when the backend hasn&#8217;t actually processed it yet.</p>
<p>Anyway the framework is far from complete and apologies for a scattered article. I just wanted to get what I had been playing with out there and perhaps get interest from others on helping with it.</p>
<p>If you are interested in helping with this perhaps comment on this article or contact me on github the repository is located <a href="https://github.com/jonathanstowell/My-Application-Framework" target="_blank">here</a>, and I will get back to you!</p>
<p>Cheers,<br />
Jon</p>
]]></content:encoded>
			<wfw:commentRss>http://jonathanstowell.com/blog/index.php/asp-net-mvc/my-application-framework/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My First Data Access Layer Amends Part 1</title>
		<link>http://jonathanstowell.com/blog/index.php/c/my-first-data-access-layer-amends-part-1</link>
		<comments>http://jonathanstowell.com/blog/index.php/c/my-first-data-access-layer-amends-part-1#comments</comments>
		<pubDate>Sun, 21 Aug 2011 18:52:34 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Data Access]]></category>

		<guid isPermaLink="false">http://jonathanstowell.com/blog/?p=407</guid>
		<description><![CDATA[Ok so yesterday I posted about a Data Access Layer (DAL) I had been working on (Article Here). Today I came across this article. The Identity Map pattern it uses taken from Martin Fowlers blog is a great idea and I decided to implement this in my DAL. I also moved away from using an [...]]]></description>
			<content:encoded><![CDATA[<p>Ok so yesterday I posted about a Data Access Layer (DAL) I had been working on (<a href="http://jonathanstowell.com/blog/index.php/c/384" title="My First Data Access Layer" target="_blank">Article Here</a>). Today I came across <a title="build your own data-access layer series" href="http://davybrion.com/blog/2009/08/build-your-own-data-access-layer-series/" target="_blank">this article</a>. The Identity Map pattern it uses taken from Martin Fowlers blog is a great idea and I decided to implement this in my DAL.</p>
<p>I also moved away from using an abstract GetAll, Add, Update, Delete etc method and instead decided to use the template pattern to perform these operations. This then means that when I need to remove objects from the object cache of the Identity Map implementation I can do so in one place instead of having to do so in every repository I create.</p>
<p>The previously abstract Update method now looks like the below. With the object being updated removed from the cache if the ExecuteWrite method is successful.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">protected abstract CommandType GetUpdateCommandType();<br />
protected abstract string GetUpdateCommandText();<br />
protected abstract ICollection&lt;IDataParameter&gt; GetUpdateParameters(T item);<br />
<br />
public bool Update(T item)<br />
{<br />
&nbsp; &nbsp; &nbsp;bool result = ExecuteWrite(GetUpdateCommandType(), GetUpdateCommandText(), GetUpdateParameters(item));<br />
&nbsp; &nbsp; &nbsp;if (result) Cache.Remove(item);<br />
&nbsp; &nbsp; &nbsp;return result;<br />
}</div></td></tr></tbody></table></div>
<p>The specifics to execute the ExecuteWrite method are now provided in the repositories by the implementation of the abstract methods you can see above.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">protected override CommandType GetUpdateCommandType()<br />
{<br />
&nbsp; &nbsp; &nbsp;return CommandType.StoredProcedure;<br />
}<br />
<br />
protected override string GetUpdateCommandText()<br />
{<br />
&nbsp; &nbsp; &nbsp;return &quot;UpdatePerson&quot;;<br />
}<br />
<br />
protected override ICollection&lt;IDataParameter&gt; GetUpdateParameters(Person item)<br />
{<br />
&nbsp; &nbsp; &nbsp;return _paramCollectionRepository.GetPersonIdFirstNameLastNameEmailParamCollection(item.PersonId,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; item.FirstName,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; item.LastName,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; item.Email);<br />
}</div></td></tr></tbody></table></div>
<p>I have implemented my Object Cache in the mapping classes of my DAL like so.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public override Person Map(IDataRecord record)<br />
{<br />
&nbsp; &nbsp; &nbsp;try<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int id = (DBNull.Value == record[_columnProvider.PersonID]) ? 0 : (int) record[_columnProvider.PersonID];<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var cachedEntity = Cache.TryToFind(typeof(Person), id);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (cachedEntity != null) return (Person)cachedEntity;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Person p = new Person();<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p.PersonId = id;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p.FirstName = (DBNull.Value == record[_columnProvider.FirstName]) ? string.Empty : (string)record[_columnProvider.FirstName];<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p.LastName = (DBNull.Value == record[_columnProvider.LastName]) ? string.Empty : (string)record[_columnProvider.LastName];<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p.Email = (DBNull.Value == record[_columnProvider.Email]) ? string.Empty : (string)record[_columnProvider.Email];<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Cache.Store(typeof(Person), id, p);<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return p;<br />
&nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp;catch (Exception)<br />
&nbsp; &nbsp; &nbsp;{ &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw;<br />
&nbsp; &nbsp; &nbsp;}<br />
}</div></td></tr></tbody></table></div>
<p>If the object can be located in the cache we no longer continue with mapping from the database and instead just return the object from the cache. If it is not in the cache we map the object and chuck it in there.</p>
<p>My object cache is just taken from the article above. However I include the code below.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public interface IObjectCache<br />
{<br />
&nbsp; &nbsp; &nbsp;object TryToFind(Type type, object id);<br />
&nbsp; &nbsp; &nbsp;void Store(Type type, object id, object entity);<br />
&nbsp; &nbsp; &nbsp;void ClearAll();<br />
&nbsp; &nbsp; &nbsp;void RemoveAllInstancesOf(Type type);<br />
&nbsp; &nbsp; &nbsp;void Remove(object entity);<br />
}<br />
<br />
public class ObjectCache : IObjectCache<br />
{<br />
&nbsp; &nbsp; &nbsp;private readonly Dictionary&lt;Type, Dictionary&lt;string, object&gt;&gt; cache = new Dictionary&lt;Type, Dictionary&lt;string, object&gt;&gt;();<br />
<br />
&nbsp; &nbsp; &nbsp;public object TryToFind(Type type, object id)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!cache.ContainsKey(type)) return null;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; string idAsString = id.ToString();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!cache[type].ContainsKey(idAsString)) return null;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return cache[type][idAsString];<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;public void Store(Type type, object id, object entity)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!cache.ContainsKey(type)) cache.Add(type, new Dictionary&lt;string, object&gt;());<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cache[type][id.ToString()] = entity;<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;public void ClearAll()<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cache.Clear();<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;public void RemoveAllInstancesOf(Type type)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (cache.ContainsKey(type))<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;cache.Remove(type);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;public void Remove(object entity)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var type = entity.GetType();<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!cache.ContainsKey(type)) return;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; string keyToRemove = null;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; foreach (var pair in cache[type])<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (pair.Value == entity)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; keyToRemove = pair.Key;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (keyToRemove != null)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;cache[type].Remove(keyToRemove);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp;}<br />
}</div></td></tr></tbody></table></div>
<p>Updated Source Code <a href="http://jonathanstowell.com/downloads/DataAccessExample21082011.zip" title="Source Code" target="_blank">Here</a>.</p>
<p>This will probably change in the future as I will probably create more realistic Domain objects that inherit from an abstract BusinessObject class which contains the primary key and implements an interface. Which may allow me to structure things in a nicer way. However for the time being this is just me playing around with some ideas which I will hopefully build upon over time.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonathanstowell.com/blog/index.php/c/my-first-data-access-layer-amends-part-1/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My First Data Access Layer</title>
		<link>http://jonathanstowell.com/blog/index.php/c/384</link>
		<comments>http://jonathanstowell.com/blog/index.php/c/384#comments</comments>
		<pubDate>Sat, 20 Aug 2011 18:00:53 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Data Access]]></category>

		<guid isPermaLink="false">http://jonathanstowell.com/blog/?p=384</guid>
		<description><![CDATA[Mainly throughout the years I have used ORM&#8217;s (Object Relational Mappers) such as LINQ to SQL, Entity Framework Code First and nHibernate to handle my database access. I mean why recreate the wheel when these tools make accessing data and returning objects so simple? With all three of them now you can even write your [...]]]></description>
			<content:encoded><![CDATA[<p>Mainly throughout the years I have used ORM&#8217;s (Object Relational Mappers) such as LINQ to SQL, Entity Framework Code First and nHibernate to handle my database access. I mean why recreate the wheel when these tools make accessing data and returning objects so simple? With all three of them now you can even write your queries in LINQ and will translate it to the relevant SQL for you! They also provide a nice abstraction from your underlying database vendor making it easy to switch from SQL Server to MySQL to Oracle. So you might ask, why am I even writing about creating a Data Access Layer from scratch? Why am I not just content with using nHibernate (My favourite from the 3 mentioned)? Well the answer is curiosity. I want to know how things work and I feel the best way to gain that understanding is to play around and write your own.</p>
<p>I also hear a lot of talk at work and from other more experienced developers about their love of just having a Data Access Object and just calling Stored Procedures. They feel you have a lot more control over the SQL you are running on the database and you experience better performance from this. From what I&#8217;ve read I&#8217;m aware that ORM&#8217;s generate SQL on the fly which does have it&#8217;s performance draw backs. Obviously when running a stored procedure no SQL needs to be generated meaning better performance. However you can cache the SQL generated by ORM&#8217;s to improve its performance and I know there are several features in nHibernate you can use to improve its performance. It&#8217;s just learning what they are! Which I am hoping to do at my new job where they claim to be hardcore nHibernate users!</p>
<p>Anyway my attempt at Data Access so far. I&#8217;ve only spent a couple days working on this so don&#8217;t be harsh! I have tried to take things I have learnt from using Generic Repository pattern using ORM&#8217;s and use it with what I have read about normal Data Access Layers. Perhaps one of the better article&#8217;s I read on the subject was this one <a title="Elegant Data Access" href="http://www.c-sharpcorner.com/UploadFile/rmcochran/elegant_dal05212006130957PM/elegant_dal.aspx" target="_blank">here</a> written by Matthew Cochran.</p>
<p>So I will start by explaining my Core.Abstract class library. Here I have the contracts which provide the Core of my data access. This is not specific to any project, implementation or database vendor. In this project I have a IDatabaseFactory which will simply provide an IDbConnection.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public interface IDatabaseFactory<br />
{<br />
&nbsp; &nbsp; &nbsp;IDbConnection DbConnection { get; }<br />
}</div></td></tr></tbody></table></div>
<p>I also have an IMapper interface which will be used for classes which will map my domain objects to the relevant database tables. Implementers of this interface will be able to return single entities or collections of entities from a passed in IDataReader object.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public interface IMapper&lt;T&gt; where T : class <br />
{<br />
&nbsp; &nbsp; &nbsp;T Map(IDataRecord record);<br />
&nbsp; &nbsp; &nbsp;T MapSingle(IDataReader reader);<br />
&nbsp; &nbsp; &nbsp;ICollection&lt;T&gt; MapCollection(IDataReader reader);<br />
}</div></td></tr></tbody></table></div>
<p>Next I have the first of three generic interfaces which will provide the main access for different types of domain objects. The first is IObjectReaderBase which will provide read access for a Object. The next IObjectWriterBase will provide create, update and delete operations for a domain object. The last IObjectKeyReaderBase provides a GetById method for Domain Objects which have a single primary key.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public interface IObjectReaderBase&lt;T&gt; where T : class<br />
{<br />
&nbsp; &nbsp; &nbsp;IDatabaseFactory DatabaseFactory { get; }<br />
&nbsp; &nbsp; &nbsp;IDbConnection Connection { get; }<br />
&nbsp; &nbsp; &nbsp;IMapper&lt;T&gt; Mapper { get; }<br />
&nbsp; &nbsp; &nbsp;ICollection&lt;T&gt; GetAll();<br />
&nbsp; &nbsp; &nbsp;T ExecuteSingle(CommandType commandType, string commandText);<br />
&nbsp; &nbsp; &nbsp;T ExecuteSingle(CommandType commandType, string commandText, ICollection&lt;IDataParameter&gt; parameters);<br />
&nbsp; &nbsp; &nbsp;ICollection&lt;T&gt; ExecuteCollection(CommandType commandType, string commandText);<br />
&nbsp; &nbsp; &nbsp;ICollection&lt;T&gt; ExecuteCollection(CommandType commandType, string commandText, ICollection&lt;IDataParameter&gt; parameters);<br />
}</div></td></tr></tbody></table></div>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public interface IObjectWriterBase&lt;T&gt; : IObjectReaderBase&lt;T&gt; where T : class<br />
{<br />
&nbsp; &nbsp; &nbsp;bool Add(T item);<br />
&nbsp; &nbsp; &nbsp;bool Add(IEnumerable&lt;T&gt; items);<br />
&nbsp; &nbsp; &nbsp;bool Update(T item);<br />
&nbsp; &nbsp; &nbsp;bool Update(IEnumerable&lt;T&gt; items);<br />
&nbsp; &nbsp; &nbsp;bool Delete(T item);<br />
&nbsp; &nbsp; &nbsp;bool Delete(IEnumerable&lt;T&gt; items);<br />
&nbsp; &nbsp; &nbsp;IUnitOfWork UnitOfWork { get; }<br />
&nbsp; &nbsp; &nbsp;bool ExecuteWrite(CommandType commandType, string commandText);<br />
&nbsp; &nbsp; &nbsp;bool ExecuteWrite(CommandType commandType, string commandText, ICollection&lt;IDataParameter&gt; parameters);<br />
}</div></td></tr></tbody></table></div>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public interface IObjectKeyReaderBase&lt;T&gt; : IObjectWriterBase&lt;T&gt; where T : class<br />
{<br />
&nbsp; &nbsp; &nbsp;T GetById(int id);<br />
}</div></td></tr></tbody></table></div>
<p>Finally I have an IUnitOfWork Interface which will encapsulate my transactions.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public interface IUnitOfWork<br />
{<br />
&nbsp; &nbsp; &nbsp;IDbTransaction Transaction { get; }<br />
&nbsp; &nbsp; &nbsp;bool IsInTransaction { get; }<br />
&nbsp; &nbsp; &nbsp;void BeginTransaction();<br />
&nbsp; &nbsp; &nbsp;void RollBackTransaction();<br />
&nbsp; &nbsp; &nbsp;bool CommitTransaction();<br />
}</div></td></tr></tbody></table></div>
<p>Ok on to the implementation of this which can be found in the Core.Concrete class library. The Database Factory is fairly simple and it just returns a new SqlConnection.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class DatabaseFactory : IDatabaseFactory<br />
{<br />
&nbsp; &nbsp; &nbsp;private IDbConnection _dbConnection;<br />
<br />
&nbsp; &nbsp; &nbsp;public IDbConnection DbConnection<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (_dbConnection == null)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _dbConnection = new SqlConnection(ConfigurationManager.ConnectionStrings[&quot;myConnectionString&quot;].ConnectionString);<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return _dbConnection;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; }<br />
}</div></td></tr></tbody></table></div>
<p>Object Reader Base contains the Unit of Work implementation, the IDbConnection which it gets from the Database Factory and the domain objects Mapper class. The class needs the Database Factory and Mapper class to be instantiated. The class contains two fairly similar methods. ExecuteSingle and ExecuteCollection which do exactly what they are called. ExecuteSingle is intended to be used for things such as GetById or a query that will only return one object. ExecuteCollection things such as GetAll or a method that will return many objects. As they are fairly similar and the only difference is which Mapping method is called I will only explain one. Fairly standard code it just creates a command from the passed in Command Type (E.g. Stored Procedure), Command Text (E.g. Stored Procedure Name) and Command Parameters (E.g. Stored Procedure Variables). This will all be specified in the Domain Objects repository class (Explained Later). If the process is in a transaction we assign the transaction to the command, we that add the parameters to the command. If the process is in a transaction we do not open the connection as it will already be open and will cause an exception (You need to keep the connection open for the entire transaction). If not in a transaction we open the connection ready to fire the command to the database. Once executed we call our Mapping method to return an object. We then close or not close our connection depending on the transaction status.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public T ExecuteSingle(CommandType commandType, string commandText, ICollection&lt;IDataParameter&gt; parameters)<br />
{<br />
&nbsp; &nbsp; &nbsp;IDbCommand command = Connection.CreateCommand();<br />
&nbsp; &nbsp; &nbsp;command.Connection = Connection;<br />
&nbsp; &nbsp; &nbsp;command.CommandText = commandText;<br />
&nbsp; &nbsp; &nbsp;command.CommandType = commandType;<br />
<br />
&nbsp; &nbsp; &nbsp;if (UnitOfWork.IsInTransaction)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; command.Transaction = UnitOfWork.Transaction;<br />
<br />
&nbsp; &nbsp; &nbsp;if (parameters != null)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; foreach (var param in parameters)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;command.Parameters.Add(param);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;try<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!UnitOfWork.IsInTransaction)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Connection.Open();<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; using (IDataReader reader = command.ExecuteReader())<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;try<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return Mapper.MapSingle(reader);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;catch (Exception)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;finally<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; reader.Close();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp;catch (Exception)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw;<br />
&nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp;finally<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!UnitOfWork.IsInTransaction) <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Connection.Close();<br />
&nbsp; &nbsp; &nbsp;}<br />
}</div></td></tr></tbody></table></div>
<p>We also declare an abstract GetAll() method which will be implemented by the inheriting repository. This way we can provide the name of the stored procedure we want to execute.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public abstract ICollection&lt;T&gt; GetAll();</div></td></tr></tbody></table></div>
<p>Next the ObjectWriterBase contains a method similar to ExecuteSingle and ExecuteCollection called ExecuteWrite. This method simply calls ExecuteNonQuery instead of executing the command and using IDataReader. This method will be used for our Create, Update and Delete operations. Again we declare abstract Add, Update and Delete methods so the inheriting class can provide the appropriate stored procedure name and parameters. We also have methods that allow a collection to be passed to them to Add, Update or Delete many records at once.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public virtual bool Add(IEnumerable&lt;T&gt; items)<br />
{<br />
&nbsp; &nbsp; &nbsp;foreach (var item in items)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Add(item);<br />
&nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp;return true;<br />
}</div></td></tr></tbody></table></div>
<p>Finally our ObjectKeyReaderBase just declares an abstract GetById method for the same reasons as previously.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public abstract T GetById(int id);</div></td></tr></tbody></table></div>
<p>The unit of work implementation is fairly simple allowing one to Begin a Transaction. Which will also open the connection for you.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public void BeginTransaction()<br />
{<br />
&nbsp; &nbsp; &nbsp;_connection.Open();<br />
&nbsp; &nbsp; &nbsp;_transaction = _connection.BeginTransaction();<br />
}</div></td></tr></tbody></table></div>
<p>Rollback a transaction.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public void RollBackTransaction()<br />
{<br />
&nbsp; &nbsp; &nbsp;_transaction.Rollback();<br />
&nbsp; &nbsp; &nbsp;_connection.Close();<br />
}</div></td></tr></tbody></table></div>
<p>Commit a transaction and run the relevant rollback if it doesn&#8217;t work.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public bool CommitTransaction()<br />
{<br />
&nbsp; &nbsp; &nbsp;if (_transaction == null)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new ApplicationException(&quot;Cannot roll back a transaction while there is no transaction running.&quot;);<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;try<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;_transaction.Commit();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;_connection.Close();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return true;<br />
&nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp;catch (Exception ex)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _transaction.Rollback();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;<br />
&nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp;finally<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ReleaseCurrentTransaction();<br />
&nbsp; &nbsp; &nbsp;}<br />
}</div></td></tr></tbody></table></div>
<p>It also contains a flag to tell you whether you are currently in a transaction.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public bool IsInTransaction<br />
{<br />
&nbsp; &nbsp; &nbsp;get { return _transaction != null; }<br />
}</div></td></tr></tbody></table></div>
<p>So now lets look at how we actually use this in relation to an object. I have a simple Person object in Entities.Conrete.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class Person<br />
{<br />
&nbsp; &nbsp; &nbsp;public int PersonId { get; set; }<br />
&nbsp; &nbsp; &nbsp;public string FirstName { get; set; }<br />
&nbsp; &nbsp; &nbsp;public string LastName { get; set; }<br />
&nbsp; &nbsp; &nbsp;public string Email { get; set; }<br />
}</div></td></tr></tbody></table></div>
<p>I then have a IPersonRepository interface in Repositories.Abstract. So far this interface just inherits from IObjectKeyReaderBase<Person> as I haven&#8217;t created any specific Person queries. I still like to create a new interface however just encase I do want to add additional methods in the future.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public interface IPersonRepository : IObjectKeyReaderBase&lt;Person&gt;<br />
{ }</div></td></tr></tbody></table></div>
<p>Finally PersonRepository is implemented in Repositories.Concrete. This class provides the Stored Procedure names and parameters to the underlying execute methods. It uses an IPersonParamCollectionRepository to get the collection of parameters. I have done this to try and create a reusable way of getting parameter collections for stored procedures which require the same parameters.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class PersonRepository : ObjectKeyReaderBase&lt;Person&gt;, IPersonRepository<br />
{<br />
&nbsp; &nbsp; &nbsp;private IPersonParamCollectionRepository _paramCollectionRepository;<br />
<br />
&nbsp; &nbsp; &nbsp;public PersonRepository(IDatabaseFactory databaseFactory, IMapper&lt;Person&gt; mapper, IPersonParamCollectionRepository paramCollectionRepository)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : base(databaseFactory, mapper)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _paramCollectionRepository = paramCollectionRepository;<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;public override ICollection&lt;Person&gt; GetAll()<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return ExecuteCollection(CommandType.StoredProcedure, &quot;GetAllPeople&quot;);<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;public override Person GetById(int id)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ICollection&lt;IDataParameter&gt; collection = _paramCollectionRepository.GetPersonIdParamCollection(id);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return ExecuteSingle(CommandType.StoredProcedure, &quot;GetPersonById&quot;, collection);<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;public override bool Add(Person item)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ICollection&lt;IDataParameter&gt; collection =<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;_paramCollectionRepository.GetFirstNameLastNameEmailParamCollection(item.FirstName, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;item.LastName,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;item.Email);<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return ExecuteWrite(CommandType.StoredProcedure, &quot;AddPerson&quot;, collection);<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;public override bool Update(Person item)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ICollection&lt;IDataParameter&gt; collection =<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;_paramCollectionRepository.GetPersonIdFirstNameLastNameEmailParamCollection(item.PersonId, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;item.FirstName,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;item.LastName, <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;item.Email);<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return ExecuteWrite(CommandType.StoredProcedure, &quot;UpdatePerson&quot;, collection);<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; public override bool Delete(Person item)<br />
&nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ICollection&lt;IDataParameter&gt; collection = _paramCollectionRepository.GetPersonIdParamCollection(item.PersonId);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return ExecuteWrite(CommandType.StoredProcedure, &quot;DeletePerson&quot;, collection);<br />
&nbsp; &nbsp; }<br />
}</div></td></tr></tbody></table></div>
<p>Now lets see the Parameter Collection Repository. In a similar method to the Repository using this to group reusable parameters together. The creation of the parameters falls to a separate class. This way if anything with an individual parameter changes, such as its data type, it only needs to be changed in one place!</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class PersonParamCollectionRepository : IPersonParamCollectionRepository<br />
{<br />
&nbsp; &nbsp; &nbsp;private IPersonParamRepository _paramRepository;<br />
<br />
&nbsp; &nbsp; &nbsp;public PersonParamCollectionRepository(IPersonParamRepository paramRepository)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _paramRepository = paramRepository;<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;public ICollection&lt;IDataParameter&gt; GetPersonIdParamCollection(int id)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ICollection&lt;IDataParameter&gt; collection = new Collection&lt;IDataParameter&gt;();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; collection.Add(_paramRepository.GetPersonIdParam(id));<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return collection;<br />
&nbsp; &nbsp; &nbsp;}<br />
}</div></td></tr></tbody></table></div>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class PersonParamRepository : IPersonParamRepository<br />
{<br />
&nbsp; &nbsp; &nbsp;private readonly IPersonColumnProvider _columnProvider;<br />
&nbsp; &nbsp; &nbsp;private readonly IDataParamHelper _dataParamHelper;<br />
<br />
&nbsp; &nbsp; &nbsp;public PersonParamRepository(IPersonColumnProvider columnProvider, IDataParamHelper dataParamHelper)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _columnProvider = columnProvider;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _dataParamHelper = dataParamHelper;<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;public IDataParameter GetPersonIdParam(int id)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return _dataParamHelper.BuildDataParameter(DbType.Int32, _columnProvider.PersonID, id);<br />
&nbsp; &nbsp; &nbsp;}<br />
}</div></td></tr></tbody></table></div>
<p>The BuildDataParameter method simply builds a parameter. Again if anything changes here it is interfaced so a new implementation can be provided and injected where it is used using Dependency Injection.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public IDataParameter BuildDataParameter(DbType dataType, string parameterName, object value)<br />
{<br />
&nbsp; &nbsp; &nbsp;IDataParameter param = new SqlParameter();<br />
&nbsp; &nbsp; &nbsp;param.DbType = dataType;<br />
&nbsp; &nbsp; &nbsp;param.Value = value ?? DBNull.Value;<br />
&nbsp; &nbsp; &nbsp;param.ParameterName = parameterName;<br />
&nbsp; &nbsp; &nbsp;return param;<br />
}</div></td></tr></tbody></table></div>
<p>The Person Column Provider class simply encapsulates the names of the columns on the Person table. Again I&#8217;ve done this so if a column name changes it only needs to be changed in this one class. Whenever I use a column name such as when I create the Data Parameters it get the name from this class.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class PersonColumnProvider : IPersonColumnProvider<br />
{<br />
&nbsp; &nbsp; &nbsp;public string PersonID<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get { return &quot;PersonID&quot;; }<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;public string FirstName<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get { return &quot;FirstName&quot;; }<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;public string LastName<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get { return &quot;LastName&quot;; }<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;public string Email<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get { return &quot;Email&quot;; }<br />
&nbsp; &nbsp; &nbsp;}<br />
}</div></td></tr></tbody></table></div>
<p>Finally perhaps a bit out of context but lets have a look at the Person Mapper class. It inherits from MapperBase which can be located in Core.Concrete.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public abstract class MapperBase&lt;T&gt; : IMapper&lt;T&gt; where T : class, new() <br />
{<br />
&nbsp; &nbsp; &nbsp;public abstract T Map(IDataRecord record);<br />
<br />
&nbsp; &nbsp; &nbsp;public T MapSingle(IDataReader reader)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; T item = null;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (reader.Read())<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;item = Map(reader);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return item;<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;public virtual ICollection&lt;T&gt; MapCollection(IDataReader reader)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ICollection&lt;T&gt; collection = new Collection&lt;T&gt;();<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while (reader.Read())<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;try<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; collection.Add(Map(reader));<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;catch (Exception)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{ &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return collection;<br />
&nbsp; &nbsp; &nbsp;}<br />
}</div></td></tr></tbody></table></div>
<p>A mapper class then just implements Map allowing it to return a single object or a collection of objects. Below simply either populates an attribute from the record that is returned from the database or populates it to an empty value if there is no record returned.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class PersonMapper : MapperBase&lt;Person&gt;<br />
{<br />
&nbsp; &nbsp; &nbsp;private readonly IPersonColumnProvider _columnProvider;<br />
<br />
&nbsp; &nbsp; &nbsp;public PersonMapper(IPersonColumnProvider columnProvider)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _columnProvider = columnProvider;<br />
&nbsp; &nbsp; &nbsp;}<br />
<br />
&nbsp; &nbsp; &nbsp;public override Person Map(IDataRecord record)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Person p = new Person();<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;p.PersonId = (DBNull.Value == record[_columnProvider.PersonID]) ? 0 : (int)record[_columnProvider.PersonID];<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;p.FirstName = (DBNull.Value == record[_columnProvider.FirstName]) ? string.Empty : (string)record[_columnProvider.FirstName];<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;p.LastName = (DBNull.Value == record[_columnProvider.LastName]) ? string.Empty : (string)record[_columnProvider.LastName];<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;p.Email = (DBNull.Value == record[_columnProvider.Email]) ? string.Empty : (string)record[_columnProvider.Email];<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return p;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; catch (Exception)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;throw;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp;}<br />
}</div></td></tr></tbody></table></div>
<p>I hope this helps someone who is just starting to look at data access layers. If anyone would like to provide comments below it would be much appreciated. Any suggestions on improvements or enhancements would be very welcome. I&#8217;m trying to learn how to do things the right way and the best way.</p>
<p>My next steps for this is to discover a way to map relationships and collections in an elegant way. Hopefully my research into this may lead me to enhancing this project to.</p>
<p>I provide the source code below. However it does contain a Caching Project and Web Project which I was just playing around with. Those two are for a later discussion! Enjoy!</p>
<p>Source Code: <a href="http://jonathanstowell.com/downloads/DataAccessExample.zip" title="Here" target="_blank">Here</a></p>
<p>PS: If anyone doesn&#8217;t have a version of Visual Studio where you can open Database Projects leave a comment and I will generate a SQL script.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonathanstowell.com/blog/index.php/c/384/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Entity Framework Code First CTP5</title>
		<link>http://jonathanstowell.com/blog/index.php/c/entity-framework-code-first-ctp5</link>
		<comments>http://jonathanstowell.com/blog/index.php/c/entity-framework-code-first-ctp5#comments</comments>
		<pubDate>Sun, 22 May 2011 11:53:14 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Entity Framework]]></category>
		<category><![CDATA[Code First]]></category>
		<category><![CDATA[Entity Framework Code First]]></category>

		<guid isPermaLink="false">http://jonathanstowell.com/blog/?p=270</guid>
		<description><![CDATA[Entity Framework Code First (EFCF) seems to be Microsoft&#8217;s answer to nHibernate. I first came across the technology a couple months ago watching a Channel 9 video from a recent MVC Conference presented by Chris Zavaleta (twitter) and was intrigued as to how useful this could be. The answer I now feel is very useful [...]]]></description>
			<content:encoded><![CDATA[<p>Entity Framework Code First (EFCF) seems to be Microsoft&#8217;s answer to nHibernate. I first came across the technology a couple months ago watching a <a href="http://channel9.msdn.com/Series/mvcConf/mvcConf-2-Chris-Zavaleta-Entity-Framework-Code-First-Domain-Driven-CRUD">Channel 9 video</a> from a recent MVC Conference presented by Chris Zavaleta (<a title="Chris Zavaleta Twitter" href="http://twitter.com/#!/chriszavaleta" target="_blank">twitter</a>) and was intrigued as to how useful this could be. The answer I now feel is very useful so keep reading!</p>
<p>Basically EFCF generates your relational database model from your object model. Which when in the early stages of a project I feel can be extremely useful. Being able to change your object model extremely quickly without the worries of creating a new database table, adding new columns to an existing table, updating your ORM or even having to rewrite, or even write new classes in your Data Access Layer (DAL) to handle the mapping of your relational domain to your object domain (Big Hassle!).</p>
<p>Having previously used LINQ to SQL as my DAL I always felt slightly frustrated with it. I like to separate things out and whilst LINQ to SQL provided a convenient way to quickly develop projects shielding me from the ugliness of having to write my own DAL, I always wanted more separation of my entities. I also found it frustrating with it not automatically loading Collections an entity may contain. Yes I can probably guess there are ways to do this but if I&#8217;m honest I didn&#8217;t have to find out in the end because EFCF came along.</p>
<p>I found EFCF maps my Object Domain to a relational database very well. The only difficulty I had is when I wanted to include additional attributes in join tables. This lead me to research into configuration files for EFCF and it turns out that if you want to have more control over how EFCF maps your object domain to the database you can. I&#8217;ve never really worked with nHibernate but have seen some examples of it on projects at work and it would seem that these configuration files are very much like the mapping xml files nHibernate uses. Apart from the EFCF configuration files are written in C# using lambda expressions to define the mappings.</p>
<p>One of the great things I discovered with EFCF is generic repositories. This to me was amazing, no longer must I write the same CRUD LINQ for different entities, I could just write one generic base repository and then inherit the generic functionality, whilst adding specific functionality where necessary. This pattern will be covered in a later blog post!</p>
<p>I used EFCF on a variety of projects before attempting this and finally decided to upgrade my final year project to use this for data access to use as an example for this blog post. Below is an example of three POCO&#8217;s.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br />73<br />74<br />75<br />76<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class User<br />
{<br />
&nbsp; &nbsp; &nbsp;#region Properties<br />
&nbsp; &nbsp; &nbsp;public int UserId { get; set; }<br />
&nbsp; &nbsp; &nbsp;public string FirstName { get; set; }<br />
&nbsp; &nbsp; &nbsp;public string LastName { get; set; }<br />
&nbsp; &nbsp; &nbsp;#endregion<br />
&nbsp; &nbsp; &nbsp;#region Collections<br />
&nbsp; &nbsp; &nbsp;public virtual ICollection Problems { get; set; }<br />
&nbsp; &nbsp; &nbsp;#endregion<br />
&nbsp; &nbsp; &nbsp;#region Constructors<br />
&nbsp; &nbsp; &nbsp;public McsUser()<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Problems = new HashSet()<br />
&nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp;#endregion<br />
}<br />
public class Problem<br />
{<br />
&nbsp; &nbsp; &nbsp;#region Primary Key<br />
&nbsp; &nbsp; &nbsp;public int ProblemId { get; set; }<br />
&nbsp; &nbsp; &nbsp;#endregion<br />
&nbsp; &nbsp; &nbsp;#region Foreign Keys<br />
&nbsp; &nbsp; &nbsp;public int StudentId { get; set; }<br />
&nbsp; &nbsp; &nbsp;public int CommunicationTypeId { get; set; }<br />
&nbsp; &nbsp; &nbsp;public int ProblemTypeId { get; set; }<br />
&nbsp; &nbsp; &nbsp;public int MitigatingCircumstanceLevelId { get; set; }<br />
&nbsp; &nbsp; &nbsp;#endregion<br />
&nbsp; &nbsp; &nbsp;#region Properties<br />
&nbsp; &nbsp; &nbsp;public DateTime? DateTime { get; set; }<br />
&nbsp; &nbsp; &nbsp;public string Outline { get; set; }<br />
&nbsp; &nbsp; &nbsp;public string MitigatingCircumstanceFile { get; set; }<br />
&nbsp; &nbsp; &nbsp;public DateTime? AbsentFrom { get; set; }<br />
&nbsp; &nbsp; &nbsp;public DateTime? AbsentUntil { get; set; }<br />
&nbsp; &nbsp; &nbsp;public DateTime? RequestedFollowUp { get; set; }<br />
&nbsp; &nbsp; &nbsp;public bool iCalAppointment { get; set; }<br />
&nbsp; &nbsp; &nbsp;public bool OutlookAppointment { get; set; }<br />
&nbsp; &nbsp; &nbsp;public virtual Student Student { get; set; }<br />
&nbsp; &nbsp; &nbsp;public virtual CommunicationType CommunicationType { get; set; }<br />
&nbsp; &nbsp; &nbsp;public virtual MitigatingCircumstanceLevel MitigatingCircumstanceLevel { get; set; }<br />
&nbsp; &nbsp; &nbsp;public virtual ProblemType ProblemCategory { get; set; }<br />
&nbsp; &nbsp; &nbsp;#endregion<br />
&nbsp; &nbsp; &nbsp;#region Collections<br />
&nbsp; &nbsp; &nbsp;public virtual ICollection ProblemCommunications { get; set; }<br />
&nbsp; &nbsp; &nbsp;public virtual ICollection AssessmentExtensions { get; set; }<br />
&nbsp; &nbsp; &nbsp;public virtual ICollection Users { get; set; }<br />
&nbsp; &nbsp; &nbsp;#endregion<br />
&nbsp; &nbsp; &nbsp;#region Constructor<br />
&nbsp; &nbsp; &nbsp;public Problem()<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ProblemCommunications = new List();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AssessmentExtensions = new List();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Users = new HashSet();<br />
&nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp;#endregion<br />
}<br />
public class CommunicationType<br />
{<br />
&nbsp; &nbsp; &nbsp;#region Primary Key<br />
&nbsp; &nbsp; &nbsp;public int CommunicationTypeId { get; set; }<br />
&nbsp; &nbsp; &nbsp;#endregion<br />
&nbsp; &nbsp; &nbsp;#region Properties<br />
&nbsp; &nbsp; &nbsp;public string Name { get; set; }<br />
&nbsp; &nbsp; &nbsp;#endregion<br />
&nbsp; &nbsp; &nbsp;#region Collections<br />
&nbsp; &nbsp; &nbsp;public virtual ICollection Problems { get; set; }<br />
&nbsp; &nbsp; &nbsp;public virtual ICollection ProblemCommunications { get; set; }<br />
&nbsp; &nbsp; &nbsp;#endregion<br />
&nbsp; &nbsp; &nbsp;#region Constructors<br />
&nbsp; &nbsp; &nbsp;public CommunicationType()<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Problems = new List();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ProblemCommunications = new List();<br />
&nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp;#endregion<br />
}</div></td></tr></tbody></table></div>
<p>Below is my Data Context, the string passed to the base class is the name of the connection string which is stored in my web.config file in my MVC project. As you can see I create Database Sets based upon my Object Domain. The on model creating override allows the developer to gain more control over the way EFCF maps Objects to the database. In my example I provide mapping classes which define primary keys, properties (columns) and relationships.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class McsContext : DbContext<br />
{<br />
&nbsp; &nbsp; &nbsp;public IDbSet Assessments { get; set; }<br />
&nbsp; &nbsp; &nbsp;public IDbSet AssessmentExtensions { get; set; }<br />
&nbsp; &nbsp; &nbsp;public IDbSet CommunicationTypes { get; set; }<br />
&nbsp; &nbsp; &nbsp;public IDbSet McsUsers { get; set; }<br />
&nbsp; &nbsp; &nbsp;public IDbSet MitigatingCircumstanceLevels { get; set; }<br />
&nbsp; &nbsp; &nbsp;public IDbSet Modules { get; set; }<br />
&nbsp; &nbsp; &nbsp;public IDbSet Problems { get; set; }<br />
&nbsp; &nbsp; &nbsp;public IDbSet ProblemCommunications { get; set; }<br />
&nbsp; &nbsp; &nbsp;public IDbSet ProblemTypes { get; set; }<br />
&nbsp; &nbsp; &nbsp;public IDbSet SeminarGroups { get; set; }<br />
&nbsp; &nbsp; &nbsp;public IDbSet Students { get; set; }<br />
&nbsp; &nbsp; &nbsp;public IDbSet StudentStatus { get; set; }<br />
&nbsp; &nbsp; &nbsp;public McsContext(string connStringName) :<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; base(connStringName)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp;protected override void OnModelCreating(DbModelBuilder modelBuilder)<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; base.OnModelCreating(modelBuilder);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; modelBuilder.Conventions.Remove();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; modelBuilder.Configurations.Add(new AssessmentMapping());<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; modelBuilder.Configurations.Add(new AssessmentExtensionMapping());<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; modelBuilder.Configurations.Add(new CommunicationTypeMapping());<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; modelBuilder.Configurations.Add(new UserMapping());<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; modelBuilder.Configurations.Add(new MitigatingCircumstanceLevelMapping());<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; modelBuilder.Configurations.Add(new ModuleMapping());<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; modelBuilder.Configurations.Add(new ProblemMapping());<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; modelBuilder.Configurations.Add(new ProblemCommunicationMapping());<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; modelBuilder.Configurations.Add(new ProblemTypeMapping());<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; modelBuilder.Configurations.Add(new SeminarGroupMapping());<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; modelBuilder.Configurations.Add(new StudentMapping());<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; modelBuilder.Configurations.Add(new StudentStatusMapping());<br />
&nbsp; &nbsp; &nbsp;}<br />
}</div></td></tr></tbody></table></div>
<p>The Configurations contain the mappings between the Entities. The class below shows a Primary Key Mapping, a One to Many Mapping and Property Mappings.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class UserMapping : EntityTypeConfiguration<br />
{<br />
&nbsp; &nbsp; &nbsp;public UserMapping()<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #region Primary Key<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.HasKey(x =&gt; x.UserId);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #endregion<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #region Foreign Keys<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #endregion<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #region Properties<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.UserName);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.LoweredUserName);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.ApplicationName);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.Email);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.Comment);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.Password);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.PasswordQuestion);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.PasswordAnswer);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.IsApproved);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.LastActivityDate);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.LastLoginDate);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.LastPasswordChangedDate);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.CreationDate);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.IsOnline);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.IsLockedOut);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.LastLockedOutDate);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.FailedPasswordAttemptCount);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.FailedPasswordAttemptWindowStart);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.FailedPasswordAnswerAttemptCount);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.FailedPasswordAnswerAttemptWindowStart);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.MobileAlias);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.IsAnonymous);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #endregion<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #region Collections<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HasMany(x =&gt; x.Problems)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .WithMany(y =&gt; y.Users)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .Map(m =&gt; { m.ToTable(&quot;UserProblems&quot;); });<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #endregion<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ToTable(&quot;Users&quot;);<br />
&nbsp; &nbsp; &nbsp;}<br />
}</div></td></tr></tbody></table></div>
<p>There are many other mappings available in the Configuration files.</p>
<p>One to Many</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; &nbsp;HasRequired(x =&gt; x.CommunicationType)<br />
&nbsp; &nbsp; &nbsp;.WithMany(y =&gt; y.Problems)<br />
&nbsp; &nbsp; &nbsp;.HasForeignKey(z =&gt; z.CommunicationTypeId)<br />
&nbsp; &nbsp; &nbsp;.WillCascadeOnDelete(false);</div></td></tr></tbody></table></div>
<p>Inheritance Mapping which you include in the abstract parent entity. Here you define a discriminator column and a unique string value for each child. This enables EFCF to cast the object to the correct child when reading relational data. There are many ways you can store Inheritance Hierarchies such as Table Per Type, Table per Hierarchy etc. Below shows inheritance mapping for four classes which all inherit from a class called Review.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; &nbsp;#region Inheritance Mapping<br />
&nbsp; &nbsp; &nbsp;this.Map(x =&gt; x.Requires(&quot;ReviewType&quot;).HasValue(&quot;1&quot;))<br />
&nbsp; &nbsp; &nbsp;.Map(x =&gt; x.Requires(&quot;ReviewType&quot;).HasValue(&quot;2&quot;))<br />
&nbsp; &nbsp; &nbsp;.Map(x =&gt; x.Requires(&quot;ReviewType&quot;).HasValue(&quot;3&quot;))<br />
&nbsp; &nbsp; &nbsp;.Map(x =&gt; x.Requires(&quot;ReviewType&quot;).HasValue(&quot;4&quot;));<br />
&nbsp; &nbsp; &nbsp;#endregion</div></td></tr></tbody></table></div>
<p>Here&#8217;s the resolution for my previous difficulty with Many to Many Mappings. The issue was that I had a scenario where an Event can contain many bands and Bands can be part of many events. However it would be useful to store the start and end time of the Bands appearance at an event, which would be stored in the join table.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class EventConfiguration : EntityTypeConfiguration<br />
{<br />
&nbsp; &nbsp; &nbsp;public EventConfiguration () {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #region Primary Key<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.HasKey(x =&gt; x.EventId);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #endregion<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #region Foreign Keys<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.HasMany(x =&gt; x.Bands)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .WithRequired(z =&gt; z.Event)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .HasForeignKey(z =&gt; z.EventId);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #endregion<br />
&nbsp; &nbsp; &nbsp;}<br />
}</div></td></tr></tbody></table></div>
<p>Band inherited from User in my example (Just an explanation for missing Primary Key / Properties.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class BandConfiguration : EntityTypeConfiguration<br />
{<br />
&nbsp; &nbsp; &nbsp;public BandConfiguration()<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #region Primary Key<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #endregion<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #region Foreign Keys<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.HasMany(x =&gt; x.BandEvents)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .WithRequired(y =&gt; y.Band)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .HasForeignKey(z =&gt; z.BandId);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #endregion<br />
&nbsp; &nbsp; &nbsp;}<br />
}<br />
public class EventBandConfiguration : EntityTypeConfiguration<br />
{<br />
&nbsp; &nbsp; &nbsp;public EventBandConfiguration()<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #region Primary Key<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.HasKey(x =&gt; new { x.EventId, x.BandId });<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #endregion<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #region Foreign Keys<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.HasRequired(x =&gt; x.Event)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .WithMany(y =&gt; y.Bands)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .HasForeignKey(z =&gt; z.EventId)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .WillCascadeOnDelete(false);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.HasRequired(x =&gt; x.Band)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .WithMany(y =&gt; y.BandEvents)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .HasForeignKey(z =&gt; z.BandId)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .WillCascadeOnDelete(false);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #endregion<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #region Properties<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.StartDateTime);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.Property(x =&gt; x.EndDateTime);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; #endregion<br />
&nbsp; &nbsp; &nbsp;}<br />
}</div></td></tr></tbody></table></div>
<p>I believe I then just had two Collections in my POCO&#8217;s that just represented the One to Many relationship between the Entity and Join table.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; &nbsp;public virtual ICollection Events { get; set; }<br />
&nbsp; &nbsp; &nbsp;public virtual ICollection Bands { get; set; }</div></td></tr></tbody></table></div>
<p>For simple joins that do not contain additional attributes EFCF allows you to model this quite easily. Just create Collections in both classes but initialise the collection as a HashSet in the Entities Constructor.</p>
<p>User Entity</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; &nbsp;#region Collections<br />
&nbsp; &nbsp; &nbsp;public virtual ICollection Problems { get; set; }<br />
&nbsp; &nbsp; &nbsp;#endregion<br />
&nbsp; &nbsp; &nbsp;#region Constructors<br />
&nbsp; &nbsp; &nbsp;public McsUser()<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Problems = new HashSet();<br />
&nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp;#endregion</div></td></tr></tbody></table></div>
<p>Problem Entity</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; &nbsp;#region Collections<br />
&nbsp; &nbsp; &nbsp;public virtual ICollection Users { get; set; }<br />
&nbsp; &nbsp; &nbsp;#endregion<br />
&nbsp; &nbsp; &nbsp;#region Constructor<br />
&nbsp; &nbsp; &nbsp;public Problem()<br />
&nbsp; &nbsp; &nbsp;{<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Users = new HashSet();<br />
&nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp;#endregion</div></td></tr></tbody></table></div>
<p>With Configuration Mappings<br />
User:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; &nbsp;#region Collections<br />
&nbsp; &nbsp; &nbsp;HasMany(x =&gt; x.Problems)<br />
&nbsp; &nbsp; &nbsp;.WithMany(y =&gt; y.Users)<br />
&nbsp; &nbsp; &nbsp;.Map(m =&gt; { m.ToTable(&quot;UserProblems&quot;); });<br />
&nbsp; &nbsp; &nbsp;#endregion</div></td></tr></tbody></table></div>
<p>You can download my sample project <a title="BournemouthUniversityEntityFramework.zip" href="http://jonathanstowell.com/downloads/BournemouthUniversityEntityFramework.zip">here!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://jonathanstowell.com/blog/index.php/c/entity-framework-code-first-ctp5/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>jQuery Unlimited Scroll</title>
		<link>http://jonathanstowell.com/blog/index.php/web-development/jquery-unlimited-scroll</link>
		<comments>http://jonathanstowell.com/blog/index.php/web-development/jquery-unlimited-scroll#comments</comments>
		<pubDate>Sat, 07 May 2011 23:44:19 +0000</pubDate>
		<dc:creator>jonathan</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Web Development]]></category>

		<guid isPermaLink="false">http://jonathanstowell.com/blog/?p=290</guid>
		<description><![CDATA[It&#8217;s been a while! I haven&#8217;t had much time to blog with beginning a new job (well not so new now) and I have learnt so much more than what I am about to post about. However I just wrote what I think is quite a cool jQuery Plugin which allows for Facebook/Twitter like AJAX [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been a while! I haven&#8217;t had much time to blog with beginning a new job (well not so new now) and I have learnt so much more than what I am about to post about. However I just wrote what I think is quite a cool jQuery Plugin which allows for Facebook/Twitter like AJAX loads when a user scrolls to the bottom of the page.</p>
<p>Quite a simple plugin:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">(function ($) {<br />
&nbsp; &nbsp; &nbsp;$.fn.unlimitedscroll = function (options) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var defaults = {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;pageSize: 10,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;url: &quot;&quot;,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;template: &quot;&quot;,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;appendTo: &quot;&quot;,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;overlay: &quot;#overlay&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; };<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var currentPage = 1;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var options = $.extend(defaults, options);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var load = function () {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;var url = options.url + &quot;?page=&quot; + currentPage;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$.getJSON(url, function (data) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $.each(data, function (i, item) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;appendData(item);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $(options.overlay).fadeOut();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;});<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; };<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var appendData = function (item) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$(options.template).tmpl(item).appendTo(options.appendTo);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; };<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return this.each(function () {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;obj = $(this);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;overlay = $(options.overlay);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$(window).scroll(function () {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ($(window).scrollTop() == $(document).height() - $(window).height()) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; currentPage++;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; overlay.fadeIn();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; load();<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });<br />
&nbsp; &nbsp; &nbsp;});<br />
})(jQuery);</div></td></tr></tbody></table></div>
<p>It simply runs an event every time the user scrolls and checks to see whether the user has reached the bottom of the page. If they have we increase the page count, fade in an ajax loading image and then make a request to the server for our JSON.</p>
<p>I&#8217;m using ASP MVC so I have a controller method like this:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">#region Json Actions<br />
public JsonResult GetPosts(int? page)<br />
{<br />
&nbsp; &nbsp; &nbsp;IList&lt;Post&gt; posts = service.GetAll().Skip(page - 1 ?? 0 * 10).Take(10).ToList();<br />
&nbsp; &nbsp; &nbsp;var slimPosts = (from p in posts select PostDTOFactory.Get(p)).AsEnumerable();<br />
&nbsp; &nbsp; &nbsp;return Json(slimPosts, JsonRequestBehavior.AllowGet);<br />
}<br />
#endregion</div></td></tr></tbody></table></div>
<p>This simply retrieve all of the instances of the item we wish to return to the view. In my case a list of Posts. It takes 10 Post items depending on how many posts are already being displayed to the user (standard paging). It them converts my object into a slimmer object, this helped me remove the circular redundancy issues you can have when serializing heavy objects. It also of course allows me to only send the data I actually need to the view, lowering bandwidth costs.</p>
<p>Once the JSON is returned the plugin appends each item returned to the specified element using jQuery Template plugin. The plugin is easily customisable using the settings as below. It allows you to setup where you will be retrieving your JSON from, the element id of your jQuery Template, the element id where you wish to append your returned items and the element id of your AJAX loading icon.</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&lt;script type=&quot;text/javascript&quot; src=&quot;@Url.Content(&quot;&gt;&lt;/script&gt;<br />
&lt;script type=&quot;text/javascript&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $(function () { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;$('#posts').unlimitedscroll({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; url: &quot;http://localhost:52247/User/GetPosts/&quot;, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; template: &quot;#post-template&quot;, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; appendTo: &quot;#posts&quot;, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; overlay: &quot;#overlay&quot; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}); &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });<br />
&lt;/script&gt;</div></td></tr></tbody></table></div>
<p>jQuery Template Example:</p>
<div class="codecolorer-container text blackboard" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; &nbsp;&lt;script id=&quot;post-template&quot; type=&quot;text/javascript&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;article id=&quot;post${PostId}&quot; class=&quot;post&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;h2&gt;&lt;a href=&quot;User/Details/${User.UserId}&quot;&gt;${User.UserName}&lt;/a&gt;&lt;/h2&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{{if User.ConnectionToCurrentUser}}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {{tmpl(User) &quot;#disconnect-template&quot;}}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{{/if}}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{{if !User.ConnectionToCurrentUser}}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {{tmpl(User) &quot;#connect-template&quot;}}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{{/if}}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;a href=&quot;User/Details/${User.UserId}&quot;&gt;&lt;img class=&quot;thumbnail alignleft&quot; src=&quot;/Content/images/user.png&quot;&gt;&lt;/a&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;${PostBody}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;div class=&quot;clear&quot;&gt;&lt;/div&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;footer class=&quot;postmeta&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;span class=&quot;btn alignleft&quot;&gt;by &lt;a href=&quot;#&quot;&gt;${User.UserName}&lt;/a&gt; on &lt;time datetime=&quot;${DateTime}&quot;pubdate&gt;${DateTime}&lt;/time&gt;&lt;/span&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {{if LikesPost}}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{{tmpl() &quot;#postdislike-template&quot;}}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {{/if}}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {{if !LikesPost}}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{{tmpl() &quot;#postlike-template&quot;}}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {{/if}}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;/footer&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;comments&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{{each Comments}}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {{tmpl($value) &quot;#comment-template&quot;}}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{{/each}}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;newcomment&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {{tmpl() &quot;#commentform-template&quot;}}<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;/newcomment&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/comments&gt;<br />
&nbsp; &nbsp; &nbsp;&lt;/script&gt;</div></td></tr></tbody></table></div>
<p>Download: <a href="http://jonathanstowell.com/downloads/jQuery/Plugins/unlimitedscroll.js">Source</a></p>
]]></content:encoded>
			<wfw:commentRss>http://jonathanstowell.com/blog/index.php/web-development/jquery-unlimited-scroll/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Served from: www.jonathanstowell.com @ 2012-02-22 23:53:55 -->
