<?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/"
	>

<channel>
	<title>Buildmasters</title>
	<atom:link href="http://www.buildmasters.com.au/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.buildmasters.com.au</link>
	<description>Just another WordPress weblog</description>
	<pubDate>Sun, 06 Jun 2010 04:52:30 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Market Data Monopoly? - Part One</title>
		<link>http://www.buildmasters.com.au/2009/05/07/market-data-monopoly/</link>
		<comments>http://www.buildmasters.com.au/2009/05/07/market-data-monopoly/#comments</comments>
		<pubDate>Thu, 07 May 2009 11:21:43 +0000</pubDate>
		<dc:creator>adam</dc:creator>
		
		<category><![CDATA[Current Projects]]></category>

		<category><![CDATA[Featured]]></category>

		<guid isPermaLink="false">http://www.buildmasters.com.au/?p=160</guid>
		<description><![CDATA[The provision of accurate and timely market data is truly the lifeblood of almost every financial services organisation worldwide. Every day these orgaisation rely on the latest stock prices, financial instrument attributes, corporate action events, rates and analytics in order to make trading decisions, reconcile their accounts and track their performance.
These requirements for a steady [...]<script type="text/javascript">SHARETHIS.addEntry({ title: "Market Data Monopoly? - Part One", url: "http://www.buildmasters.com.au/2009/05/07/market-data-monopoly/" });</script>]]></description>
			<content:encoded><![CDATA[<p>The provision of accurate and timely market data is truly the lifeblood of almost every financial services organisation worldwide. Every day these orgaisation rely on the latest stock prices, financial instrument attributes, corporate action events, rates and analytics in order to make trading decisions, reconcile their accounts and track their performance.</p>
<p>These requirements for a steady stream of vast quantities of data have give rise to a number of extremely successful market data organisations who collate their data from the exchanges and brokers and package it up so it can easily be consumed by banks, investment managers and anyone else who can afford to sign up for an account.</p>
<p><img class="alignnone size-full wp-image-161" title="bloomberg_logo" src="http://www.buildmasters.com.au/wp-content/uploads/2009/05/bloomberg_logo.gif" alt="bloomberg_logo" width="205" height="56" /></p>
<p>Two of the major players in the market data business are Bloomberg and Reuters. Their market data products are very similar and allow their clients to subscribe to market data feeds via several mechanisms, including &#8216;Pay-As-You-Go&#8217; whereby you can make requests for information (eg prices and attributes) about a particular financial instrument (eg BHP Ordinary Shares) and they send back the details, for which you pay &#8216;Per Security&#8217; - currently around $2(USD), depending on security tyep (Bond, Equity, Derivative, etc). Alternatively you can subscribe to entire segments of security data in a &#8216;batch&#8217;, for instance &#8216;Asian Equities&#8217;, and receive the entire universe of those securities daily. The choice of mechanism really depends on how many securities of a particular type the client needs data for and what the most cost effective mechanism is at the time.<span id="more-160"></span></p>
<p><img class="size-full wp-image-162 alignright" title="reuters_logo" src="http://www.buildmasters.com.au/wp-content/uploads/2009/05/reuters_logo.png" alt="reuters_logo" width="223" height="69" /></p>
<p>The most common problem that subscribers to these market data services face is the degree to which ther are tied in to their provider and their ability to switch their services between providers when a &#8216;better&#8217; deal can be struck with a competitor. Quite often the internal systems within the subscriber&#8217;s organisation have been designed to interface with a particular provider and mechanism - probably the provider/mechanism that offered the best deal when the systems were developed. Over time as more cost effective services become available or when data volumes increase to the point that the original mechanism is no longer cost effective the subscribers may wish to &#8216;replumb&#8217; their feeds but cannot do so due to the high costs involved.</p>
<p>Lets illustrate this problem with a real life example&#8230;.</p>
<p>Back in 2006 a large Australian investment management organisation in Sydney began a program of work to replatform their entire Front and Middle Office systems in order to ready themselves for their planned business strategy. This program involved integrating market data from Bloomberg and a number of smaller market data providers.</p>
<p>The initial release of the new platform involved relatively small volumes of financial instrument (security) data and therefore the Bloomberg Datalicense &#8216;Per Security&#8217; mechanism offered the most flexible and cost-effective solution, allowing us to request the 1000 or so securities that we needed each day, incurring costs of around $2000/month -  well within our budget.</p>
<p>One year later, during the next phase of the program we increased our security volumes to 8000, resulting in a significant increase in the month costs for market data from Bloomberg. At this point we were getting numerous calls from Reuters who wanted to pitch their market data services to us and were also looking at an alternative service from Bloomberg that would allow us to bulk buy data rather than paying &#8216;Per Security&#8217;.</p>
<p>&lt;&lt;To Be Continued&gt;&gt;</p>
<p><a href="http://sharethis.com/item?&wp=2.7.1&amp;publisher=e7067adf-03c9-4684-bd43-845f964c4034&amp;title=Market+Data+Monopoly%3F+-+Part+One&amp;url=http%3A%2F%2Fwww.buildmasters.com.au%2F2009%2F05%2F07%2Fmarket-data-monopoly%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.buildmasters.com.au/2009/05/07/market-data-monopoly/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Tales from the War Room</title>
		<link>http://www.buildmasters.com.au/2009/04/29/tales-from-the-war-room/</link>
		<comments>http://www.buildmasters.com.au/2009/04/29/tales-from-the-war-room/#comments</comments>
		<pubDate>Wed, 29 Apr 2009 07:09:46 +0000</pubDate>
		<dc:creator>adam</dc:creator>
		
		<category><![CDATA[Current Projects]]></category>

		<category><![CDATA[Eagle PACE Development]]></category>

		<guid isPermaLink="false">http://www.buildmasters.com.au/?p=157</guid>
		<description><![CDATA[With out 3rd major software release due in 40 days success is really reliant on some pretty effective collaboration between the multiple moving parts that need to come together on the day like one big well-oiled machine. That&#8217;s why I&#8217;m so glad that we setup our &#8216;War Room&#8217; meeting. Each morning at 9am 20 indivduals descend [...]<script type="text/javascript">SHARETHIS.addEntry({ title: "Tales from the War Room", url: "http://www.buildmasters.com.au/2009/04/29/tales-from-the-war-room/" });</script>]]></description>
			<content:encoded><![CDATA[<p>With out 3rd major software release due in 40 days success is really reliant on some pretty effective collaboration between the multiple moving parts that need to come together on the day like one big well-oiled machine. That&#8217;s why I&#8217;m so glad that we setup our &#8216;War Room&#8217; meeting. Each morning at 9am 20 indivduals descend on Meeting Room One from their various teams and take stock of progress over the previous 24hrs.</p>
<p>From the top we have : <strong>the Delivery Manager</strong>, ultimately responsible for the successful implementation of the release into Production; <strong>the Project Manager</strong>, reponsible for coordinating the campaign and keeping us all revved up; <strong>the Test Director</strong> and test team leads, responsible for executing 500 test cases with 100% success rates through System Test, Joint System Test  and Joint Acceptance Testing;<strong> the Trading System BA</strong>, responsible for design and development of the BlackRock Trading Platform component; <strong>the Data Management System team lead</strong>, responsible for the 40+ integration components they feed data throughout the solution; <strong>the Enterprise Services team lead</strong>, responsible for scheduling of data feeds; <strong>the Environments team lead</strong>, reponsible for servers, hardware and dealing with the spate of City-wide power-cuts we&#8217;ve had recently!!! Finally there&#8217;s<strong> the &#8216;Stats Guy&#8217;</strong>, responsible for compiling an impressive array of graphs and statistics that boil down the infite number of variables that all the other members generate during any given day into something that can meaningfully be discussed in under 45 minutes.<span id="more-157"></span></p>
<p>All up a motley crew and some might wonder how a large group like that can be productive. Well lets start with the &#8216;why?&#8217; question - Why do we need to sit down EVERY morning - how much can happen in 24hrs to make it worth while??</p>
<p>The answer is that an enormous amount of things happen in 24hrs - mainly due to the fact we are now running &#8216;Prod-Like&#8217; - ie. we are simulating in out Joint System test environment exactly what will happen in Production when we go live. This means running 2 batch cycles per day loading data from our Administrator and Trading Systems and send thing data downstream - TWICE!</p>
<p>We are also trading on 30 different security types - exactly as will be the case when we release the system to our Front Office users.</p>
<p>We are fixing 10-15 defects daily and executing a similar number of test cases.</p>
<p>On top of all that are the numerous daily issues, risks and surprises that make this such an interesting place to work.</p>
<p>Top issues, defects and risks are tracked, discussed and resolved on our &#8216;War Board&#8217; - see picture :</p>
<p><a href="http://www.buildmasters.com.au/wp-content/uploads/2009/04/board-issues.jpg"><img class="alignnone size-medium wp-image-158" title="board-issues" src="http://www.buildmasters.com.au/wp-content/uploads/2009/04/board-issues-300x225.jpg" alt="" width="620" height="298" /></a></p>
<p>The &#8216;health check&#8217; is our &#8216;Spider&#8217; which shows which interfaces between systems in the current code line are running &#8216;clean&#8217; :</p>
<p><a href="http://www.buildmasters.com.au/wp-content/uploads/2009/04/board-spider.jpg"><img class="alignnone size-full wp-image-159" title="board-spider" src="http://www.buildmasters.com.au/wp-content/uploads/2009/04/board-spider.jpg" alt="" width="618" height="375" /></a></p>
<p>The session is usually over in less than an hour and everyone leaves the room with the right direction for the day. Without this process our ability to keep on track would be significantly more difficult - so if you don&#8217;t have a War Room of your own then it&#8217;s time to start thinking about it - Let Battle Commence!</p>
<p>ScrumMaster</p>
<p> </p>
<p> </p>
<p> </p>
<p><a href="http://sharethis.com/item?&wp=2.7.1&amp;publisher=e7067adf-03c9-4684-bd43-845f964c4034&amp;title=Tales+from+the+War+Room&amp;url=http%3A%2F%2Fwww.buildmasters.com.au%2F2009%2F04%2F29%2Ftales-from-the-war-room%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.buildmasters.com.au/2009/04/29/tales-from-the-war-room/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Buildmasters dataBRIDGE</title>
		<link>http://www.buildmasters.com.au/2009/04/20/buildmasters-databridge/</link>
		<comments>http://www.buildmasters.com.au/2009/04/20/buildmasters-databridge/#comments</comments>
		<pubDate>Mon, 20 Apr 2009 14:23:16 +0000</pubDate>
		<dc:creator>adam</dc:creator>
		
		<category><![CDATA[Data Analysis]]></category>

		<guid isPermaLink="false">http://www.buildmasters.com.au/?p=155</guid>
		<description><![CDATA[dataBRIDGE brings you flexibility and freedom to choose the combination of market data services that best fit your business. Historically financial services organisations have been limited in their ability to shop around for market data and acheive value for money from their service providers. Users of Bloomberg Datalicense &#8216;Per Security&#8217; find it difficult to migrate [...]<script type="text/javascript">SHARETHIS.addEntry({ title: "Buildmasters dataBRIDGE", url: "http://www.buildmasters.com.au/2009/04/20/buildmasters-databridge/" });</script>]]></description>
			<content:encoded><![CDATA[<p style="text-align: left;"><img src="/wp-content/uploads/2009/04/box.jpg" alt="" width="283" height="259" />dataBRIDGE brings you flexibility and freedom to choose the combination of market data services that best fit your business. Historically financial services organisations have been limited in their ability to shop around for market data and acheive value for money from their service providers. Users of Bloomberg Datalicense &#8216;Per Security&#8217; find it difficult to migrate to their &#8216;BackOffice&#8217; product when the volumes of security data they need make it more economical to do so.</p>
<p style="text-align: left;">Ideally you need to be able to subscribe to a blend of services from a number of providers in order to meet your market data needs in th emost economical way possible. Buildmasters dataBRIDGE provides this capability and more.</p>
<p style="text-align: left;">For more information email us by filling out our form here: <a href="/contact/">Buildmasters dataBRIDGE</a></p>
<p><a href="http://sharethis.com/item?&wp=2.7.1&amp;publisher=e7067adf-03c9-4684-bd43-845f964c4034&amp;title=Buildmasters+dataBRIDGE&amp;url=http%3A%2F%2Fwww.buildmasters.com.au%2F2009%2F04%2F20%2Fbuildmasters-databridge%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.buildmasters.com.au/2009/04/20/buildmasters-databridge/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Code Branching gone mad!</title>
		<link>http://www.buildmasters.com.au/2009/03/23/code-branching-gone-mad/</link>
		<comments>http://www.buildmasters.com.au/2009/03/23/code-branching-gone-mad/#comments</comments>
		<pubDate>Tue, 24 Mar 2009 04:30:43 +0000</pubDate>
		<dc:creator>adam</dc:creator>
		
		<category><![CDATA[Current Projects]]></category>

		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://www.buildmasters.com.au/?p=153</guid>
		<description><![CDATA[Question : What happens in the last year of a multi-year, multi-million dollar, multi-release program of development and business change???
Answer : All the hard stuff that has been left to the end has to be delivered in parallel, in overlapping releases and in double quick time before the money runs out&#8230;oh, and if you&#8217;re really [...]<script type="text/javascript">SHARETHIS.addEntry({ title: "Code Branching gone mad!", url: "http://www.buildmasters.com.au/2009/03/23/code-branching-gone-mad/" });</script>]]></description>
			<content:encoded><![CDATA[<p><strong>Question</strong> : <em>What happens in the last year of a multi-year, multi-million dollar, multi-release program of development and business change???</em></p>
<p><strong>Answer</strong> : <em>All the hard stuff that has been left to the end has to be delivered in parallel, in overlapping releases and in double quick time before the money runs out&#8230;oh, and if you&#8217;re really unluck you&#8217;ll have to upgrade some of the applications from the earlier releases too.</em></p>
<p>This is a reality for us at the moment on our project at one of Australia&#8217;s largest fund management companies. Despite shifting requirements and architecture we have managed to deliver 2 successful major releases over the last 2 years and yet our biggest challenge lays ahead of us.</p>
<p>So far we have built a powerful Investment Data Management Platfor using the Eagle PACE product as a base, into which we have integrated accounting feeds from Hiport, market data feeds from Bloomberg, Factset and S&amp;P. On the other end we have integrated 3 trading platforms - Charles River (for Equities and Enterprise Compliance), Imagine (for Derivatives) and BlackRock Aladdin (for Fixed Income). On top of all that we have integrated a Performance and Anlaytics system (StatPro), Recs System (Smartstream TLM) and Corporate Actions system (Smartstream Coacs). To really finish things off we have added a Data Mart layer to support Internal reporting via Business Objects and External Reporting via SS&amp;C Pages - PHEW!!</p>
<p>How can there be more you&#8217;re asking yourselves? Well now we have to feed Registry Data into the mix too from multiple registries and switch off several legacy systems ( not forgetting remediation of a reasonably long list of small access and excel based apps).</p>
<p>Finally we are upgrading Eagle, Charles River, StatPro and SS&amp;C Pages&#8230;.all before December 31st 2009!</p>
<p>As you can imagine we have alot of issues to overcome, and there&#8217;s not enough room on this page to discuss them all, but I thought I&#8217;d share with you one of the many issues that just get overlooked when these gran plans are hatched - code branching!!</p>
<p>For the uninitiated code branching (and merging) is the situation you find your self in when you have multiple release dates of the same code base running concurrently. In a perfect world you would only have 2 lines of code - Development (known also as &#8216;THE TRUNK&#8217;) and Production Support (known also as &#8216;THE PROD BRANCH&#8217;). In this perfect world when &#8216;hot fixes&#8217; are applied to the &#8216;PROD BRANCH&#8217; they are then merged into &#8216;THE TRUNK&#8217; to keep it in line with with what is in Production, that way when a major release is deployed to Production from THE TRUNK it includes all the hotfixes that have been accumulated since the last major release.</p>
<p>Our problem is we have mul;tiple teams working on multiple &#8216;major&#8217; and &#8216;minor&#8217; releases of the same application (The Data Management Platform). As a result we have THE TRUNK, THE PROD BRANCH and 2 additional branches - one for an upgrade release and another for a parallal major release. Confused? I&#8217;m not surprised! Here&#8217;s a photo of the whiteboard after our team meeting this morning..</p>
<p><a href="http://www.buildmasters.com.au/wp-content/uploads/2009/03/code_branches.jpg"><img class="alignnone size-full wp-image-154" title="code_branches" src="http://www.buildmasters.com.au/wp-content/uploads/2009/03/code_branches.jpg" alt="" width="590" height="375" /></a></p>
<p>The release order runs left to right. The PROD BRANCH is always on the left as a deplpoyment to Production by the support team can happen anytime, next comes &#8216;91&#8242; which represents an upgrade of our data management platform toolset to version 9.1, then there&#8217;s 3A - the current major release we are working on - due to go to Prod in June. Finally there &#8216;4&#8242; that is due to go to Prod in Septemberbut development has to start now - hence another branch!!!</p>
<p>The arrows at the top indicate where all the overhead exists with this situation. Changes in earlier branches must be merged into later branches to keep them up-to-date. The can be quite time consuming - particularly as some of our components (in the ETL space) are binary and can&#8217;t be auto-magically merged by our source code repository tools (Subversion).</p>
<p>We aren&#8217;t exactly sure what the impact will be on our project plan - we intend to perform the merge tasks as we go to avoid breaking huge numbers of our automated unit tests. A cursory estimate is indicating about an additional 20% to each development task - a total of 1 man month in total. I&#8217;ll be talking to our PM today - hope he&#8217;s in a good mood!!</p>
<p>Scrum Master</p>
<p> </p>
<p><a href="http://sharethis.com/item?&wp=2.7.1&amp;publisher=e7067adf-03c9-4684-bd43-845f964c4034&amp;title=Code+Branching+gone+mad%21&amp;url=http%3A%2F%2Fwww.buildmasters.com.au%2F2009%2F03%2F23%2Fcode-branching-gone-mad%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.buildmasters.com.au/2009/03/23/code-branching-gone-mad/feed/</wfw:commentRss>
		</item>
		<item>
		<title>A Lesson From Kalashnikov</title>
		<link>http://www.buildmasters.com.au/2008/11/26/a-lesson-from-kalashnikov/</link>
		<comments>http://www.buildmasters.com.au/2008/11/26/a-lesson-from-kalashnikov/#comments</comments>
		<pubDate>Wed, 26 Nov 2008 23:45:59 +0000</pubDate>
		<dc:creator>adam</dc:creator>
		
		<category><![CDATA[Current Projects]]></category>

		<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://www.buildmasters.com.au/?p=151</guid>
		<description><![CDATA[Ok, don&#8217;t panic, we haven&#8217;t gone gun crazy, but we picked up an interesting analogy today from one of our business sponsors. It went something like this : &#8220;The Kalashnikov AK47 only has 13 moving parts and is the most successful weapon ever invented, remember this when you start designing your next software delivery. Keeping [...]<script type="text/javascript">SHARETHIS.addEntry({ title: "A Lesson From Kalashnikov", url: "http://www.buildmasters.com.au/2008/11/26/a-lesson-from-kalashnikov/" });</script>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.buildmasters.com.au/wp-content/uploads/2008/11/ak47.jpg"><img class="alignnone size-medium wp-image-152 alignleft" style="float: left;" title="ak47" src="http://www.buildmasters.com.au/wp-content/uploads/2008/11/ak47.jpg" alt="" width="143" height="111" /></a>Ok, don&#8217;t panic, we haven&#8217;t gone gun crazy, but we picked up an interesting analogy today from one of our business sponsors. It went something like this : &#8220;The Kalashnikov AK47 only has 13 moving parts and is the most successful weapon ever invented, remember this when you start designing your next software delivery. Keeping things simple is the key to building something that is reliable, will accept the abuses imposed by our operating environment and will stand the test of time&#8221;.</p>
<p>This is a more colourful way of repeating our mantra &#8220;Keep IT Simple Stupid&#8221;. Applying this &#8216;KISS&#8217; principle has enabled us to deliver robust and reliable software into a production environment over and over again. More importantly that software is Maintainable and Extensible - qualities that are often forgotten by the project team, most of whom have no intention of hanging around after &#8216;Go-Live&#8217;.</p>
<p>If I were to pick the biggest challenge we have faced on our current project it would be the transition of project to &#8216;Business As Usual&#8217;. Despite a large comms budget and endless workshop sessions in an attempt to engage the future custodians of our systems it has been an uphill struggle. Our team has suffered less than others, despite being one of the larger elements of the overall program, and the one thing that has made the process more palatable is the fact that we have tried to reduce complexity at every opportunity. If I were to list the top 5 tips for &#8216;Keeping It Simple&#8217; they would be :</p>
<ol>
<li>Don&#8217;t accept the early version s of the solution architecture without thorough review. It has probably been conceived from a 60,000ft view and is likely to be over engineered. Review it, Challenge it, Simplify It</li>
<li>Any steps that result in writing less code is good, as long as it is not at the expense of true requirements. Less code means less testing and fewer points of failure.</li>
<li>Keep the number of &#8217;systems&#8217; involved in an end-to-end process as few as possible. Each step in the chain is a potential point of failure, and with different systems using different logging and exception mechanisms means the process of diagnosing issues becomes a phorensic excercise of huge proportions.</li>
<li>Standardize your development process and avoid &#8216;Specialists&#8217;. Each member of your design, development and testing team should be as interchangeable as possible. They should subscribe to a common set of goals and processes, and should collaborate regularly. If a team member is working in isolation for long periods of time you can bet he/she is building a problem.</li>
<li>Integrate small chunks of functionality at a time. It&#8217;s much easiler to resolve issues and refactor components if you and introducing small changes to the code base regularly rather than attempting large integrations. Your options are severley limited if you find problems after a large integration (in terms of time and resources), especially if a signisifcant redesign is needed.</li>
</ol>
<p><a href="http://sharethis.com/item?&wp=2.7.1&amp;publisher=e7067adf-03c9-4684-bd43-845f964c4034&amp;title=A+Lesson+From+Kalashnikov&amp;url=http%3A%2F%2Fwww.buildmasters.com.au%2F2008%2F11%2F26%2Fa-lesson-from-kalashnikov%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.buildmasters.com.au/2008/11/26/a-lesson-from-kalashnikov/feed/</wfw:commentRss>
		</item>
		<item>
		<title>The search for a C# DAL code generator that actually works. Part 3: the solution.</title>
		<link>http://www.buildmasters.com.au/2008/09/04/the-search-for-a-c-dal-code-generator-that-actually-works-part-3-the-solution/</link>
		<comments>http://www.buildmasters.com.au/2008/09/04/the-search-for-a-c-dal-code-generator-that-actually-works-part-3-the-solution/#comments</comments>
		<pubDate>Thu, 04 Sep 2008 08:28:44 +0000</pubDate>
		<dc:creator>tubby taylor</dc:creator>
		
		<category><![CDATA[Code Generation]]></category>

		<category><![CDATA[code generation C# DAL .NET]]></category>

		<guid isPermaLink="false">http://www.buildmasters.com.au/?p=148</guid>
		<description><![CDATA[part 1
part 2
part 3
In part 2 of this series, I outlined my requirements for an ideal DAL generator.
Well, not having found any tool out there that meets my criteria, I ended up writing the tool myself, meeting all but one of my objectives [I dont handle stored procedures yet].
&#160;
Sql Server 2005 is the target DBMS [...]<script type="text/javascript">SHARETHIS.addEntry({ title: "The search for a C# DAL code generator that actually works. Part 3: the solution.", url: "http://www.buildmasters.com.au/2008/09/04/the-search-for-a-c-dal-code-generator-that-actually-works-part-3-the-solution/" });</script>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.buildmasters.com.au/2008/09/04/the-search-for-a-c-dal-code-generator-that-actually-works-part-1-the-problem-2">part 1</a><br />
<a href="http://www.buildmasters.com.au/2008/09/04/the-search-for-a-c-dal-code-generator-that-actually-works-part-2-the-requirements-2">part 2</a><br />
<a href="http://www.buildmasters.com.au/2008/09/04/the-search-for-a-c-dal-code-generator-that-actually-works-part-3-the-solution">part 3</a></p>
<p>In part 2 of this series, I outlined my requirements for an ideal DAL generator.</p>
<p>Well, not having found any tool out there that meets my criteria, I ended up writing the tool myself, meeting all but one of my objectives [I dont handle stored procedures yet].<br />
&nbsp;<br />
Sql Server 2005 is the target DBMS for now, using VS2005 as the compiler.</p>
<p>Lets walk through how to use the tool.</p>
<ul>
<li>From the command line, the tool is invoked like this.</li>
</ul>
<div style="padding-left: 30px;"><code>mycodegentool.exe config.xml</code></div>
<p><br/></p>
<ul>
<li>The simplest config.xml file is</li>
</ul>
<div style="padding-left: 30px;"><code>&lt;CodeGen&gt;<br />
&nbsp;&lt;Directory&gt;D:\development\codegenExample\myDatabase&lt;/Directory&gt;<br />
&nbsp;&lt;ConnectionString&gt;Data Source=.;Initial Catalog=myDatabase;<br />
&nbsp;&nbsp;&nbsp;&nbsp;Integrated Security=SSPI;&lt;/ConnectionString&gt;<br />
&nbsp;&lt;ConcurrencyColumn&gt;update_date&lt;/ConcurrencyColumn&gt;<br />
&lt;CodeGen&gt;</code></div>
<p><br/></p>
<div style="padding-left: 30px;">This will give you a DAL dll with every table and view of the database in it, and handle concurrency for any table that that has an update_date field.</div>
<p><br/></p>
<ul>
<li>To get a unit test dll as well, add this xml fragment to the config file.</li>
</ul>
<div style="padding-left: 30px;"><code>&lt;UnitTest&gt;<br />
&nbsp;&lt;Directory&gt;D:\development\codegenExample\myDatabase\CodeGenUnitTest&lt;/Directory&gt;<br />
&lt;/UnitTest&gt;</code></div>
<p><br/></p>
<p>This takes care of the plumbing. Now reference the DAL dll from your business layer dll, and happy porcelain coding.</p>
<p>Here are a few use case scenarios in actually using the DAL from your business layer.</p>
<ul>
<li>Load up a table.</li>
</ul>
<div style="padding-left: 30px;"><code>ProductsFactory factory = new ProductsFactory();<br />
List rows = factory.LoadAll( connection ) ;<br />
Console.WriteLine( rows.Count ) ;</code></div>
<p><br/></p>
<ul>
<li>Quicker way to see have many rows in a table.</li>
</ul>
<div style="padding-left: 30px;"><code>ProductsFactory factory = new ProductsFactory();<br />
int rowcount = factory.GetRowCount( connection ) ;</code></div>
<p><br/></p>
<ul>
<li>Load up a specific row from a table using the primary key.</li>
</ul>
<div style="padding-left: 30px;"><code>int id = 17 ;<br />
ProductsFactory factory = new ProductsFactory();<br />
Products product = factory.LoadByPrimaryKey( connection, id ) ;</code></div>
<p><br/></p>
<ul>
<li>Load up a set of rows from a table based on custom search criteria.</li>
</ul>
<div style="padding-left: 30px;"><code>bool discontinued = true ;<br />
ProductsFactory factory = new ProductsFactory();<br />
List rows = factory.LoadByDiscontinued( connection, discontinued ) ;</code></div>
<p><br/></p>
<div style="padding-left: 30px;">To add custom search criteria to a table or view, add this xml fragment to the config file.
</div>
<p><br/></p>
<div style="padding-left: 30px;"><code>&lt;Tables&gt;<br />
	&nbsp;&lt;Table Class="Products" &gt;<br />
		&nbsp;&nbsp;&lt;Methods&gt;<br />
			&nbsp;&nbsp;&nbsp;&lt;Method Name="LoadByDiscontinued" where="LoadByDiscontinued.sql"&gt;<br />
				&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Parameters&gt;<br />
					&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Parameter Name="discontinued" Type="bool?" /&gt;<br />
				&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/Parameters&gt;<br />
			&nbsp;&nbsp;&nbsp;&nbsp;&lt;/Method&gt;<br />
		&nbsp;&nbsp;&lt;/Methods&gt;<br />
	&nbsp;&lt;/Table&gt;<br />
&lt;Tables&gt;</code></div>
<p><br/></p>
<div style="padding-left: 30px;">where the contents of the sql file are</div>
<p><br/></p>
<div style="padding-left: 30px;"><code>where discontinued = @discontinued order by productname</code></div>
<p><br/></p>
<ul>
<li>Get a row&#8217;s parent row.</li>
</ul>
<div style="padding-left: 30px;">Here we are walking the employee hierarchary using ootb generated methods - cool.</div>
<p><br/></p>
<div style="padding-left: 30px;"><code>EmployeesFactory factory = new EmployeesFactory();</p>
<p>// robert - the pleb<br />
int? employeeId = 7;<br />
Employees robert = factory.LoadByPrimaryKey( connection, employeeId);<br />
Assert.AreEqual( robert.FirstName, "Robert" ) ;</p>
<p>// robert reports to steven<br />
Employees steven = robert.parentEmployeesByReportsTo( connection ) ;<br />
Assert.AreEqual(steven.FirstName, "Steven");</p>
<p>// steven reports to andrew<br />
Employees andy = steven.parentEmployeesByReportsTo( connection);<br />
Assert.AreEqual(andy.FirstName, "Andrew");</p>
<p>// andrew is the big cheese<br />
Employees nevilleNobody = andy.parentEmployeesByReportsTo(connection);<br />
Assert.IsNull(nevilleNobody);</code></div>
<p><br/></p>
<ul>
<li>Get a row&#8217;s children rows.</li>
</ul>
<div style="padding-left: 30px;">Here we start with an order, then go up to get its customer, then go down to get all the orders of this customer - powerful pattern in a few lines of code.</div>
<p><br/></p>
<div style="padding-left: 30px;"><code>OrdersFactory factory = new OrdersFactory();<br />
int orderId = 10289 ;</p>
<p>// get an order<br />
Orders order = factory.LoadByPrimaryKey( connection, orderId); </p>
<p>// the customer for this order<br />
Customers customer = order.parentCustomersByCustomerID( connection) ; </p>
<p>// all the orders of this customer<br />
List orderList = customer.childOrdersByCustomerID( connection ) ;<br />
</code></div>
<p><br/></p>
<ul>
<li>Load up from a view.</li>
</ul>
<div style="padding-left: 30px;">Same as loading from a table.</div>
<p><br/></p>
<div style="padding-left: 30px;"><code>Alphabetical_list_of_productsFactory factory = new Alphabetical_list_of_productsFactory();<br />
List rows = factory.LoadAll( connection ) ;</code></div>
<p><br/></p>
<ul>
<li>Load up from a custom query.</li>
</ul>
<div style="padding-left: 30px;">Same as loading from a table, with some extra config.</div>
<p><br/></p>
<div style="padding-left: 30px;"><code>CustomerOrderFactory factory = new CustomerOrderFactory();<br />
List rows = factory.LoadByRegion( connection, "Quebec" );<br />
List rows2 = factory.LoadByCustomer( connection, "quick" ) ;</code></div>
<p><br/></p>
<div style="padding-left: 30px;">The config in this case would be<br />
<code><br />
&lt;Queries&gt;<br />
&nbsp;&lt;Query Class="CustomerOrder" CodeFile="CustomerOrder.cs" Select="CustomerOrder.sql" &gt;<br />
&nbsp;&nbsp;&lt;Methods&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;Method Name="LoadByRegion" Where="LoadByRegion.sql"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;Parameters&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;Parameter Name="region" Type="string" /&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;/Parameters&gt;<br />
&nbsp;&nbsp;&lt;/Method&gt;<br />
&nbsp;&lt;/Methods&gt;<br />
&nbsp;&nbsp;&lt;Method Name="LoadByCustomer" Where="LoadByCustomer.sql"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;Parameters&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;Parameter Name="customerId" Type="string" /&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;/Parameters&gt;<br />
&nbsp;&nbsp;&lt;/Method&gt;<br />
&nbsp;&lt;/Query&gt;<br />
&lt;/Queries&gt;<br />
</code></div>
<p></br></p>
<div style="padding-left: 30px;">Here we have a customer order view, for display on a web page data grid for example.</p>
<p>The CustomerOrder.sql file contains</p>
<p><code>select * from customers c, orders o</code></p>
<p>whilst the LoadByCustomer method has the following criteria in the config sql file reference</p>
<p><code>where c.customerid = o.customerid<br />
and c.customerid = @customerid<br />
order by c.companyname, o.orderdate</code></p>
<p>and the LoadByRegion method&#8217;s where clause is</p>
<p><code>where c.customerid = o.customerid<br />
and isnull(c.region, '') = isnull(@region, '')<br />
order by c.companyname, o.orderdate</code>
</div>
<p><br/></p>
<ul>
<li>Insert a new row</li>
</ul>
<div style="padding-left: 30px;"><code>OrdersFactory factory = new OrdersFactory();<br />
Orders order = new Orders() ; // create a new row in memory<br />
order.CustomerID = 123;<br />
order.EmployeeID = 7 ;<br />
order = factory.Save( order, connection ) ; // does the insert</code></div>
<p><br/></p>
<ul>
<li>Update an existing row</li>
</ul>
<div style="padding-left: 30px;"><code>OrdersFactory factory = new OrdersFactory();<br />
int orderId = 10289 ;<br />
Orders order = factory.LoadByPrimaryKey( connection, orderId); // get an order<br />
order.ShipPostalCode = "2565"<br />
order = factory.Save( order, connection ) ; // does the update</code></div>
<p><br/></p>
<ul>
<li>Insert then update a row</li>
</ul>
<div style="padding-left: 30px;"><code>OrdersFactory factory = new OrdersFactory();</p>
<p>Orders order = new Orders() ; // create a new row in memory<br />
order.CustomerID = 123;<br />
order.EmployeeID = 7 ;<br />
order = factory.Save( order, connection ) ; // does the insert</p>
<p>order.ShipPostalCode = "2565"<br />
order = factory.Save( order, connection ) ; // does the update</code></div>
<p><br/></p>
<ul>
<li>Delete an existing row</li>
</ul>
<div style="padding-left: 30px;"><code>OrdersFactory factory = new OrdersFactory();</p>
<p>int orderId = 10289 ;<br />
Orders order = factory.LoadByPrimaryKey( connection, orderId); // get an order</p>
<p>order.MarkForDelete = true ;<br />
factory.Save( order, connection ) ; // does the delete</code></div>
<p><br/></p>
<ul>
<li>Negative use case - get a concurrency error.</li>
</ul>
<div style="padding-left: 30px;"><code>TestTableFactory factory = new TestTableFactory();</p>
<p>TestTable alice = factory.LoadByPrimaryKey( connection, 12345 ); // get a row<br />
TestTable bob   = factory.LoadByPrimaryKey( connection, 12345 ); // get it again</p>
<p>alice.update_date = DateTime.Now ;<br />
bob.update_date   = DateTime.Now ;</p>
<p>alice = factory.Save( alice, connection ) ; // does the save ok<br />
bob   = factory.Save( bob, connection )   ; // will throw a concurrency exception</code></div>
<p><br/></p>
<ul>
<li>Negative use case - get a save error when saving a stale object</li>
</ul>
<div style="padding-left: 30px;"><code>OrdersFactory factory = new OrdersFactory();</p>
<p>int orderId = 10289 ;<br />
Orders order = factory.LoadByPrimaryKey( connection, orderId); // get an order</p>
<p>order.ShipPostalCode = "2565"<br />
factory.Save( order, connection ) ; // does the update - ok</p>
<p>order.ShipPostalCode = "2000"<br />
factory.Save( order, connection ) ; // will throw a stale row exception</code></div>
<p><br/></p>
<ul>
<li>Many users simultaneously inserting rows into a table.</li>
</ul>
<div style="padding-left: 30px;">
In this example, a total of 5000 rows will be inserted into a table by 50 threads running in parallel. The table in question has a monotonically increasing non-identity integer ID primary key field, and therefore it is a contention hotspot.<br />
<br/><br />
In the first version of this use case, the inserts fail, as the code and sql that determine the next primary key value are not protected against concurrent threads. The test fails with the error &#8220;Violation of PRIMARY KEY constraint &#8216;PK_TestTable3&#8242;. Cannot insert duplicate key&#8221;.<br />
<code><br />
protected void InsertLotsOfRowsInParallel()<br />
{<br />
&nbsp;using ( MyThreadPoolManager tpm = new MyThreadPoolManager( 50, 5000 ))<br />
&nbsp;{<br />
&nbsp;&nbsp;for (int i = 1; i <= rowsToInsert; i++)<br />
&nbsp;&nbsp;&nbsp;tpm.Queue( InsertOneRow() ) ;<br />
&nbsp;&nbsp;tpm.WaitUntilAllFinished() ;<br />
&nbsp;}<br />
}<br />
// every invocation of this method runs in its own thread<br />
protected void InsertOneRow()<br />
{<br />
&nbsp;using (TransactionScope transaction =<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new TransactionScope(TransactionScopeOption.RequiresNew))<br />
&nbsp;{<br />
&nbsp;&nbsp;using (SqlConnection connection = new SqlConnection( _connectionString ) )<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;connection.Open();<br />
&nbsp;&nbsp;&nbsp;TestTable3Factory factory = new TestTable3Factory();<br />
&nbsp;&nbsp;&nbsp;TestTable3 obj = new TestTable3();<br />
&nbsp;&nbsp;&nbsp;// BAD: get the next available ID = max(ID) + 1<br />
&nbsp;&nbsp;&nbsp;obj.ID = select max(ID) + 1 from the table<br />
&nbsp;&nbsp;&nbsp;obj.update_date = DateTime.Now;<br />
&nbsp;&nbsp;&nbsp;// insert the row - this will fail with PRIMARY KEY constraint violation<br />
&nbsp;&nbsp;&nbsp;obj = factory.Save(obj, connection);<br />
&nbsp;&nbsp;&nbsp;transaction.Complete(); // commit - wont get here<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
}<br />
</code><br />
<br/><br />
In the correct version of this use case, the codegen tool has ootb capability to handle this common scenario. The tool will escalate the lock around the next primary key value and serialise access to the table, giving everyone a warm fuzzy feeling.<br />
</br/><br />
<code><br />
// every invocation of this method runs in its own thread<br />
protected void InsertOneRow()<br />
{<br />
&nbsp;using (TransactionScope transaction =<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new TransactionScope(TransactionScopeOption.RequiresNew))<br />
&nbsp;{<br />
&nbsp;&nbsp;using (SqlConnection connection = new SqlConnection( _connectionString ) )<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;connection.Open();<br />
&nbsp;&nbsp;&nbsp;TestTable3Factory factory = new TestTable3Factory();<br />
&nbsp;&nbsp;&nbsp;TestTable3 obj = new TestTable3();<br />
&nbsp;&nbsp;&nbsp;// GOOD: the tool will get the next available ID, the safe way<br />
&nbsp;&nbsp;&nbsp;obj.ID = factory.GetNextId( connection, TestTable3.Column_ID, true );<br />
&nbsp;&nbsp;&nbsp;obj.update_date = DateTime.Now;<br />
&nbsp;&nbsp;&nbsp;// insert the row - now it works<br />
&nbsp;&nbsp;&nbsp;obj = factory.Save(obj, connection);<br />
&nbsp;&nbsp;&nbsp;transaction.Complete(); // commit - aha<br />
&nbsp;&nbsp;}<br />
&nbsp;}<br />
}<br />
</code>
</div>
<p><br/></p>
<ul>
<li>Here are a few <a href="http://reflector.red-gate.com/Download.aspx">.NET Reflector</a> screen dumps of the DAL layer that the tool generates for Northwind.</li>
</ul>
<div>
<a href="http://members.optusnet.com.au/~casaletto1/northwind.png"><img src="http://members.optusnet.com.au/~casaletto1/northwind.png" alt="northwind row" width="600" height="300" /> </a></p>
<div>This is what the Orders row object looks like.</div>
</div>
<p><br/></p>
<div>
<a href="http://members.optusnet.com.au/~casaletto1/northwindFactory.png"><img src="http://members.optusnet.com.au/~casaletto1/northwindFactory.png" alt="northwind factory" width="600" height="300" /> </a></p>
<div>And the corresponding factory object for the Orders table.</div>
</div>
<p><br/></p>
<div>
<a href="http://members.optusnet.com.au/~casaletto1/northwindCustomQuery.png"><img src="http://members.optusnet.com.au/~casaletto1/northwindCustomQuery.png" alt="northwind custom query" width="600" height="300" /> </a></p>
<div>Here we have a custom query object that is a join between Customers and Orders tables.</div>
</div>
<p><br/></p>
<div>
<a href="http://members.optusnet.com.au/~casaletto1/northwindCustomQueryFactory.png"><img src="http://members.optusnet.com.au/~casaletto1/northwindCustomQueryFactory.png" alt="northwind custom query factory" width="600" height="300" /> </a></p>
<div>And the corresponding factory object.</div>
</div>
<p><br/></p>
<div>
<a href="http://members.optusnet.com.au/~casaletto1/northwindCodegenUnitTest.png"><img src="http://members.optusnet.com.au/~casaletto1/northwindCodegenUnitTest.png" alt="northwind DAL code gen unit test " width="600" height="300" /> </a></p>
<div>This screen shot shows some of the generated code involved in unit testing the DAL. Here, in the insert phase, each table is being populated and saved in referential integrity order, with pre and post row counts, object state, and field values being asserted.
</div>
</div>
<p><br/></p>
<ul>
<li>One of the databases that I have recently codegened is the popular <a href="http://www.dotnetnuke.com/">DotNetNuke</a> database.</li>
</ul>
<div style="padding-left: 30px;">You can download my DAL for DNN <a href="http://members.optusnet.com.au/~casaletto1/alby.dnn.codegen.dll">here</a> and also download the corresponding unit test dll <a href="http://members.optusnet.com.au/~casaletto1/alby.dnn.codegen.test.dll">here</a>.<br />
I recommend  <a href="http://reflector.red-gate.com/Download.aspx">.NET Reflector</a> to inspect the generated code.<br />
<br/><br />
Contact <a href="http://buildmasters.com.au">Buildmasters</a> if you would like a DAL generated for your database.
</div>
<p><br/></p>
<ul>
<li>This is the to do list for the tool</li>
</ul>
<div style="padding-left: 30px;">
<ul>
<li>Make sure it compiles and works under <a href="http://www.mono-project.com/Main_Page">Mono</a> and <a href="http://www.debian.org/">Debian Linux</a>.
	</li>
<li>Make sure it compiles and runs under VS2008.</li>
<li>Extend to target SqlServer 2008, MySql, Oracle databases.</li>
<li>Extend to handle stored procedures.</li>
</ul>
</div>
<p><br/></p>
<p>So far I have used the tool against 13 corporate, vendor and public databases, and it has my made my programming experience easier, faster, and more reliable.<br />
<br/><br />
I do not think about the DAL layer at all now - it just works.<br />
<br/></p>
<p><a href="http://sharethis.com/item?&wp=2.7.1&amp;publisher=e7067adf-03c9-4684-bd43-845f964c4034&amp;title=The+search+for+a+C%23+DAL+code+generator+that+actually+works.+Part+3%3A+the+solution.&amp;url=http%3A%2F%2Fwww.buildmasters.com.au%2F2008%2F09%2F04%2Fthe-search-for-a-c-dal-code-generator-that-actually-works-part-3-the-solution%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.buildmasters.com.au/2008/09/04/the-search-for-a-c-dal-code-generator-that-actually-works-part-3-the-solution/feed/</wfw:commentRss>
		</item>
		<item>
		<title>The search for a C# DAL code generator that actually works. Part 2: the requirements.</title>
		<link>http://www.buildmasters.com.au/2008/09/04/the-search-for-a-c-dal-code-generator-that-actually-works-part-2-the-requirements-2/</link>
		<comments>http://www.buildmasters.com.au/2008/09/04/the-search-for-a-c-dal-code-generator-that-actually-works-part-2-the-requirements-2/#comments</comments>
		<pubDate>Thu, 04 Sep 2008 07:57:02 +0000</pubDate>
		<dc:creator>tubby taylor</dc:creator>
		
		<category><![CDATA[Code Generation]]></category>

		<category><![CDATA[code generation C# DAL .NET]]></category>

		<guid isPermaLink="false">http://www.buildmasters.com.au/?p=147</guid>
		<description><![CDATA[part 1
part 2
part 3
Now that I have outlined the reasons why current DAL tools do not satisfy me, I will list my requirements for the ideal DAL code gen tool.
The tool should:

Generate the DAL for the whole database in one hit, not table by table, generating all non-system tables and views out of the box.


Have [...]<script type="text/javascript">SHARETHIS.addEntry({ title: "The search for a C# DAL code generator that actually works. Part 2: the requirements.", url: "http://www.buildmasters.com.au/2008/09/04/the-search-for-a-c-dal-code-generator-that-actually-works-part-2-the-requirements-2/" });</script>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.buildmasters.com.au/2008/09/04/the-search-for-a-c-dal-code-generator-that-actually-works-part-1-the-problem-2">part 1</a><br />
<a href="http://www.buildmasters.com.au/2008/09/04/the-search-for-a-c-dal-code-generator-that-actually-works-part-2-the-requirements-2">part 2</a><br />
<a href="http://www.buildmasters.com.au/2008/09/04/the-search-for-a-c-dal-code-generator-that-actually-works-part-3-the-solution">part 3</a></p>
<p>Now that I have outlined the reasons why current DAL tools do not satisfy me, I will list my requirements for the ideal DAL code gen tool.</p>
<p>The tool should:</p>
<ul>
<li>Generate the DAL for the whole database in one hit, not table by table, generating all non-system tables and views out of the box.</li>
</ul>
<ul>
<li>Have a simple pleasant configuration file experience.<br />
Ideally, the minimum configuration required would be a connection string to the database, and a directory path to which files are generated.</li>
</ul>
<ul>
<li>Be able to support the addition of custom query objects and custom criteria clauses, and to do so in an easy manner.</li>
</ul>
<ul>
<li>Create the DAL in a separate dll, so that the source code of my business rules layer contains only business rules code.</li>
</ul>
<ul>
<li>Be a command line tool, so I can run it as part of my build process, and via cruise control, regenerating the DAL every night and on-demand during the day, keeping it in synchronised with the underlying database schema.</li>
</ul>
<ul>
<li>Create objects that do not hold any database locks.<br />
Therefore all objects returned from the DAL are to be disconnected.</li>
</ul>
<ul>
<li>Be designed with concurrency in mind from the ground up.<br />
No joke, the vast majority of systems that I have encountered over the last two decades have not taken concurrency into account.<br />
Consider this scenario: Alice and Bob both read row A from a table in the database.<br />
Alice modifies her copy of row A and saves it back to the database.<br />
Bob then changes his copy and successfully saves it back.<br />
Congratulations, your database is now corrupt.<br />
This is incorrect behaviour, as Bob should have received a concurrency exception when he attempted to save his stale row.<br />
The DAL tool should support this out of the box.<br />
This is plumbing - the programmer should not have to worry about it.<br />
Concurrency handling is especially important now that we live a disconnected data set world.</li>
</ul>
<ul>
<li>Uses nullable types. I do not want to explicitly check for nulls before I get or set a field.<br />
The tool should do it.</li>
</ul>
<ul>
<li>Not use events.</li>
</ul>
<ul>
<li>Be designed with database transactions in mind from the ground up, and should work with implicit transactions via TransactionScope, or explicit BYO transactions.</li>
</ul>
<ul>
<li>Generate clean, understandable code that is easy to follow and debug.</li>
</ul>
<ul>
<li>Generate deterministic predictable code, so that small schema changes do not cause large diffs.</li>
</ul>
<ul>
<li>Use the referential integrity of the database itself to automatically generate accessor methods on objects that allow you to walk the database tree.<br />
These accessors to parent and child objects are to be lazy populated, ie when the accessor is invoked..</li>
</ul>
<ul>
<li>Have a simple object model using the factory pattern.<br />
TRow : RowBase ,  List&lt;TRow&gt;, TFactory: FactoryBase.</li>
</ul>
<ul>
<li>At buildmasters, we have a very strong test ethic.<br />
Even generated code needs to be tested.<br />
The tool should auto generate unit tests to code cover the generated DAL code.<br />
The unit tests should perform the following tasks in one database transaction:</p>
<ul>
<li>Insert a row into every table, populating each field, read the rows back, and assert the row counts and field values.</li>
<li>Update the inserted rows, changing the values of each field, read the rows back, and assert the row counts and field values.</li>
<li>Delete the inserted rows, and assert the row counts.</li>
<li>Rollback the transaction [unit tests should leave no footprint in the database].</li>
</ul>
</li>
</ul>
<ul>
<li>Have the following persistance patterns:
<ol>
<li>Successfully persisting a row object invalidates the object, so it cannot be saved again, and returns the latest version of the row in a new object.</li>
<li>Persisting an unmodified row object does nothing.</li>
<li>If a table does not have a primary key, its row objects cannot to be persisted.<br />
This is a classic case of bad database design. Every table needs a primary key.</li>
<li>A standard persistance mode that follows the rules of database integrity:<br />
A new memory row object can only be inserted, not updated, based on primary key.<br />
A row object that is read from the database can only be updated or deleted, based on primary key and concurrency cookie, and only if the concurrency cookie is still valid.</li>
<li>An ETL persistence mode:<br />
Persisting a row object involves trying an update, and failing that, an insert is attempted, all based on primary key.<br />
The concurrency flag is ignored.<br />
This mode of operation is used in batch ETL type tasks where you just want to transfer or inject a whole bunch of rows in to a table, whether that table is in the same database or not, and maybe on a different connection.</li>
</ol>
</li>
</ul>
<ul>
<li>Provide a DAL wrapper around legacy stored procedures.<br />
Im not a big fan of TSQL [see my post <a href="http://www.buildmasters.com.au/2008/06/24/sqlserver2005-move-from-tsql-to-sqlclr-and-save-your-project">here</a> ].<br />
I have seen many instances of whole systems that have been written in TSQL, where the business rules have been buried away in unmaintainable several-thousand-line TSQL stored procs, as opposed to having the business rules in a proper SOA/business tier written in a high level language like C#.<br />
It is a pain to debug TSQL and it does not scale.<br />
But sometimes you will inherit such a mess, so at least the DAL tool can hide it behind a nice C# interface.</li>
</ul>
<p>In part 3 of this article, I will outline a tool that meets these requirements.</p>
<p><a href="http://sharethis.com/item?&wp=2.7.1&amp;publisher=e7067adf-03c9-4684-bd43-845f964c4034&amp;title=The+search+for+a+C%23+DAL+code+generator+that+actually+works.+Part+2%3A+the+requirements.&amp;url=http%3A%2F%2Fwww.buildmasters.com.au%2F2008%2F09%2F04%2Fthe-search-for-a-c-dal-code-generator-that-actually-works-part-2-the-requirements-2%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.buildmasters.com.au/2008/09/04/the-search-for-a-c-dal-code-generator-that-actually-works-part-2-the-requirements-2/feed/</wfw:commentRss>
		</item>
		<item>
		<title>The search for a C# DAL code generator that actually works. Part 1: the problem.</title>
		<link>http://www.buildmasters.com.au/2008/09/04/the-search-for-a-c-dal-code-generator-that-actually-works-part-1-the-problem-2/</link>
		<comments>http://www.buildmasters.com.au/2008/09/04/the-search-for-a-c-dal-code-generator-that-actually-works-part-1-the-problem-2/#comments</comments>
		<pubDate>Thu, 04 Sep 2008 07:55:34 +0000</pubDate>
		<dc:creator>tubby taylor</dc:creator>
		
		<category><![CDATA[Code Generation]]></category>

		<category><![CDATA[code generation C# DAL .NET]]></category>

		<guid isPermaLink="false">http://www.buildmasters.com.au/?p=145</guid>
		<description><![CDATA[part 1
part 2
part 3
Besides developers, the database is your company’s greatest asset.
The data in your database, your ability to get at it, shape it, analyse it, report on it, turn it in to understandable meaningful information, is what gives your company competitive advantage.
I have been designing, using, optimising and programming against relational databases for over [...]<script type="text/javascript">SHARETHIS.addEntry({ title: "The search for a C# DAL code generator that actually works. Part 1: the problem.", url: "http://www.buildmasters.com.au/2008/09/04/the-search-for-a-c-dal-code-generator-that-actually-works-part-1-the-problem-2/" });</script>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.buildmasters.com.au/2008/09/04/the-search-for-a-c-dal-code-generator-that-actually-works-part-1-the-problem-2">part 1</a><br />
<a href="http://www.buildmasters.com.au/2008/09/04/the-search-for-a-c-dal-code-generator-that-actually-works-part-2-the-requirements-2">part 2</a><br />
<a href="http://www.buildmasters.com.au/2008/09/04/the-search-for-a-c-dal-code-generator-that-actually-works-part-3-the-solution">part 3</a></p>
<p>Besides developers, the database is your company’s greatest asset.</p>
<p>The data in your database, your ability to get at it, shape it, analyse it, report on it, turn it in to understandable meaningful information, is what gives your company competitive advantage.</p>
<p>I have been designing, using, optimising and programming against relational databases for over 20 years. DB2, Oracle, SqlServer, Sybase, Access, and MySql are some of the major relational databases engines that I have worked with, and DAO, ADO, ADO.NET, visual studio dataset designer, nHibernate, CSLA, codesmith, and LINQ are some of the tools and DAL technologies that I have used to get at the those databases.</p>
<p>In all that time, I have been frustrated with all of the above DAL methods of accessing data, for various reasons that I will discuss below.</p>
<p>I found that I was spending too much time stuffing around trying to placate or work around the DAL technology and not enough time just getting the job done.</p>
<p>Developers should spend their time writing the porcelain (the business rules that are specific to solving a business problem that cannot be generated by a tool) and very little time writing and working around with the plumbing (the repeatable monkey code infrastructure that can be generated by a tool).</p>
<p>Let us take the visual studio dataset designer for example.<br />
The visual studio DAL tool is fairly good, but I have several issues with it which have caused me a great considerable frustration .</p>
<ul>
<li>For one, it does things one table at a time. This is very cumbersome when one has 100+ tables in a database that needs to be DALd.</li>
</ul>
<ul>
<li>It is also very slow. When I right click on the designer, my pc freezes for several seconds until the context menu pops up. FWIW I have a high spec dev box.</li>
</ul>
<ul>
<li>The generated code does not compile in SQLCLR safe mode.<br />
Why can&#8217;t something I generate in visual studio work in SQLCLR safe mode?<br />
Hello Microsoft. Visual studio and Sql Server are both your products.<br />
The problem is that the designer inserts a bunch of delegates and events into the generated code, and events use synchronisation objects, which are forbidden in SQLCLR safe mode, and there is no way to prevent generation of these events every time you touch the designer.<br />
Who actually uses those events anyway?<br />
Am I the only person that thinks that events are overrated and over used.<br />
For app support teams, events are a nightmare to debug.<br />
One needs innate familiarity with the code to visualise the execution flow, even when using a debugger.<br />
In my experience, events have been more trouble than their worth over the years.</li>
</ul>
<ul>
<li>Null checking. The code generated does not use nullable types for some reason, so every time I get or set a property, I have to write code to first test for null, otherwise the dataset code will kindly throw an exception.<br />
I just want to set a property – 1 line of code, not 5, please.</li>
</ul>
<ul>
<li>Also, after your program is complied, you don’t know if or when the underlying database schema has changed. Guess when you find out – runtime!<br />
I want the DAL layer to be in sync with the actual underlying database schema at all times.<br />
If I had a command line interface to the visual studio dataset designer, I could regenerate the DAL layer through my continuous build process and have confidence in the accuracy of my DAL.</li>
</ul>
<ul>
<li>Another annoyance is that sometimes the designer changes column orders, seemingly at random, and a small change in the designer causes illogical reordering in the designer.cs file, making diffs hard to read.</li>
</ul>
<ul>
<li>The typed data adapter classes do not expose their contained SqlCommand objects publicly, so I cannot associate an explicit transaction to them.</li>
</ul>
<p>The other data access methods don’t do the job for me either:</p>
<ul>
<li>CSLA: the version I used was based on XSLT templates – OMG -–enough said.</li>
</ul>
<ul>
<li>nHibernate: getting closer, doesn’t handle my requirements see below.</li>
</ul>
<ul>
<li>linq2sql and EF4. Microsoft&#8217;s latest attempts at ORM. Yep that&#8217;s right - plural - there&#8217;s 2 of them (to be fair linq2sql is sql server only). Linq2sql&#8217;s DataContext cache-based architecture will cause you to pull your remaining hair out, especially in n-tier scenarios, as <a href="http://www.west-wind.com/weblog/posts/134095.aspx">here</a>. EF4, the first real version of entity framework that works, in visual studio 2010, is the long term best bet, but you&#8217;ll need to invest quite a bit of time and energy to get to EF4 nirvana, to learn it philosophy and quirks, which are not obvious at first glance, and if you don&#8217;t keeps things simple, you can really get your knickers in a knot.
</li>
</ul>
<p>In part 2 of this article, I will outline my requirements for an ideal DAL code generator.</p>
<p><a href="http://sharethis.com/item?&wp=2.7.1&amp;publisher=e7067adf-03c9-4684-bd43-845f964c4034&amp;title=The+search+for+a+C%23+DAL+code+generator+that+actually+works.+Part+1%3A+the+problem.&amp;url=http%3A%2F%2Fwww.buildmasters.com.au%2F2008%2F09%2F04%2Fthe-search-for-a-c-dal-code-generator-that-actually-works-part-1-the-problem-2%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.buildmasters.com.au/2008/09/04/the-search-for-a-c-dal-code-generator-that-actually-works-part-1-the-problem-2/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Legacy MetaData Analysis</title>
		<link>http://www.buildmasters.com.au/2008/08/21/data-analysis-services/</link>
		<comments>http://www.buildmasters.com.au/2008/08/21/data-analysis-services/#comments</comments>
		<pubDate>Fri, 22 Aug 2008 06:09:00 +0000</pubDate>
		<dc:creator>adam</dc:creator>
		
		<category><![CDATA[Data Analysis]]></category>

		<category><![CDATA[Featured]]></category>

		<category><![CDATA[data dictionary]]></category>

		<category><![CDATA[database structure]]></category>

		<category><![CDATA[metadata]]></category>

		<guid isPermaLink="false">http://www.buildmasters.com.au/?p=136</guid>
		<description><![CDATA[Do you have complex legacy systems with extensive database components? Do you need to map out what you have in order to move forward efficiently?
This kind of analysis is time consuming and error prone if attempted manually. We have a fast and efficient automated solution that will save you time and money during this type [...]<script type="text/javascript">SHARETHIS.addEntry({ title: "Legacy MetaData Analysis", url: "http://www.buildmasters.com.au/2008/08/21/data-analysis-services/" });</script>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.buildmasters.com.au/wp-content/uploads/2008/08/lightbulb.jpg"><img class="alignnone size-medium wp-image-134 alignleft" style="float: left;" title="lightbulb" src="http://www.buildmasters.com.au/wp-content/uploads/2008/08/lightbulb.jpg" alt="" width="64" height="74" /></a>Do you have complex legacy systems with extensive database components? Do you need to map out what you have in order to move forward efficiently?</p>
<p>This kind of analysis is time consuming and error prone if attempted manually. We have a fast and efficient automated solution that will save you time and money during this type of project.</p>
<p>Some of the issues your Business Analysis Team will face are:</p>
<ul>
<li>Legacy System with 000&#8217;s of Tables, Views, Stored Procedures and Functions</li>
<li>Complex interdependencies between them</li>
<li>No documentation and no original developers</li>
<li>No-one knows what is being used and what isn&#8217;t</li>
<li>Fragile environment as small changes in one place can have large impacts elsewhere</li>
</ul>
<p style="text-align: center;"><span id="more-136"></span></p>
<table border="0" width="100%">
<tbody>
<tr>
<td align="center"><img class="aligncenter" title="contactus" src="http://www.buildmasters.com.au/wp-content/uploads/2008/08/contactus.jpg" alt="" width="51" height="59" /></td>
</tr>
<tr>
<td align="center"><a class="aligncenter" title="Contact Us" href="http://www.buildmasters.com.au/contact" target="_self">CONTACT US</a></td>
</tr>
</tbody>
</table>
<p style="text-align: center;">The Buildmasters MetaData Analysis process uses a combination of industry standard tools and our expertice to generate a comprehansive and easy to navigate resource that will enable your own team perform their analysis.</p>
<table border="0" width="100%">
<tbody>
<tr>
<td align="center"><img class="alignnone size-full wp-image-139" title="sample-report" src="http://www.buildmasters.com.au/wp-content/uploads/2008/08/sample-report.jpg" alt="" width="46" height="58" /></td>
</tr>
<tr>
<td align="center"><a class="aligncenter" style="text-align: center;" title="Buildmasters Data Analysis Report" href="http://www.buildmasters.com.au/sample" target="_blank">SEE A SAMPLE REPORT HERE</a></td>
</tr>
</tbody>
</table>
<p> </p>
<p>An engagement with us involves the following non-intrusive steps:</p>
<h3>1. Proof Of Concept</h3>
<p>This is a low cost exercise that allows us to sample the source database systems and produce a report covering a fragment of the databases for appraisal by the client. The process will typicall involve:</p>
<ol>
<li>Extraction of database structure from source database(s)</li>
<li>Parsing and Cleansing of Metadata</li>
<li>Load into the Buildmasters Metabase for integrity checking and further cleansing</li>
<li>Processing via the Buildmasters Database Documentation Tool</li>
<li>Publishing of Documentation either online or in a portable help file</li>
</ol>
<p><a class="aligncenter" style="text-align: center;" title="Buildmasters Data Analysis Report" href="http://www.buildmasters.com.au/sample" target="_blank"><img class="alignnone size-full wp-image-137 aligncenter" title="dataanalysis" src="http://www.buildmasters.com.au/wp-content/uploads/2008/08/dataanalysis.png" alt="" width="471" height="624" /></a></p>
<p style="text-align: center;">____________________________________</p>
<h3>2. Comprehensive Data Analysis Report</h3>
<p>Having refined the output during the Proof-Of-Concept the full report is generated and cleansed by the Buildmasters Team before being delivered to the client for final acceptance. An example of one of our meta-data analysis reports is available <a class="aligncenter" title="Buildmasters Data Analysis Report" href="http://www.buildmasters.com.au/sample" target="_blank">here</a>, generated using the sample Northwind database.</p>
<p>The Proof-Of-Concept (POC) step guarantees our clients expectations are met before having incur significant analysis costs. If you could like to find out more about this service please contact us using the link below.</p>
<table border="0" width="100%">
<tbody>
<tr>
<td align="center"><img class="aligncenter" title="contactus" src="http://www.buildmasters.com.au/wp-content/uploads/2008/08/contactus.jpg" alt="" width="51" height="59" /></td>
</tr>
<tr>
<td align="center"><a class="aligncenter" title="Contact Us" href="http://www.buildmasters.com.au/contact" target="_self">CONTACT US</a></td>
</tr>
</tbody>
</table>
<hr />
<p><a href="http://sharethis.com/item?&wp=2.7.1&amp;publisher=e7067adf-03c9-4684-bd43-845f964c4034&amp;title=Legacy+MetaData+Analysis&amp;url=http%3A%2F%2Fwww.buildmasters.com.au%2F2008%2F08%2F21%2Fdata-analysis-services%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.buildmasters.com.au/2008/08/21/data-analysis-services/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Scrum Secret #2 - low tech rocks!</title>
		<link>http://www.buildmasters.com.au/2008/08/01/a-victory-for-scrum/</link>
		<comments>http://www.buildmasters.com.au/2008/08/01/a-victory-for-scrum/#comments</comments>
		<pubDate>Sat, 02 Aug 2008 03:12:34 +0000</pubDate>
		<dc:creator>adam</dc:creator>
		
		<category><![CDATA[Current Projects]]></category>

		<category><![CDATA[Development]]></category>

		<category><![CDATA[Scrum]]></category>

		<category><![CDATA[agile]]></category>

		<category><![CDATA[methodology]]></category>

		<guid isPermaLink="false">http://www.buildmasters.com.au/?p=130</guid>
		<description><![CDATA[There are a number of elements to SCRUM that really work well for us. One of the most obvious features is our &#8216;SCRUM Wall&#8217;, where we &#8216;publish&#8217; all the work items that form part of the current sprint to &#8216;The World&#8217;.

The Wall is primarily for the team, but it’s surprising how many ‘outsiders’ take a [...]<script type="text/javascript">SHARETHIS.addEntry({ title: "Scrum Secret #2 - low tech rocks!", url: "http://www.buildmasters.com.au/2008/08/01/a-victory-for-scrum/" });</script>]]></description>
			<content:encoded><![CDATA[<p>There are a number of elements to SCRUM that really work well for us. One of the most obvious features is our &#8216;SCRUM Wall&#8217;, where we &#8216;publish&#8217; all the work items that form part of the current sprint to &#8216;The World&#8217;.</p>
<p style="text-align: center;"><a href="http://www.buildmasters.com.au/wp-content/uploads/2008/08/scrum-wall.jpg"><img class="alignnone size-full wp-image-131 aligncenter" title="scrum-wall" src="http://www.buildmasters.com.au/wp-content/uploads/2008/08/scrum-wall.jpg" alt="" width="591" height="375" /></a></p>
<p style="text-align: left;">The Wall is primarily for the team, but it’s surprising how many ‘outsiders’ take a real interest. Initially there’s the comments about ‘nice wall - but a bit low-tech isn’t it’, to which we respond - ‘that’s the point’. The great thing about the Wall is that each card is a tangible thing, representing a tangible deliverable. Rather than being locked away in a spreadsheet or web app (though we do use TACKLE to track our tasks electronically to - more on that later) the cards can be accessed easily by everyone.</p>
<p style="text-align: left;">The cards typically begin life with a one-liner describing a deliverable, and estimate of how long it will take and the initials of one of the developers. However it doesn’t take long before the card has evolved with the scribblings of several members of the team as more information is discovered.</p>
<p style="text-align: center;"><a href="http://www.buildmasters.com.au/wp-content/uploads/2008/08/card1.jpg"><img class="alignnone size-full wp-image-133 aligncenter" title="card1" src="http://www.buildmasters.com.au/wp-content/uploads/2008/08/card1.jpg" alt="" width="211" height="159" /></a></p>
<p style="text-align: left;">Quite often one card will become two or three as the iterative process of understanding more about the task unfolds. The pure simplicity of the wall means that things don’t get forgotten or fall off the radar - every thought and new discovery is captured quickly and easily.</p>
<p style="text-align: left;">The wall only represents 2 weeks of work at a time - a Sprint. This means that every 2 weeks the wall gets cleared. The completed tasks are archived. The items that are not complete or blocked are taken down and form the basis of the &#8216;Backlog&#8217; for the next sprint, in addition to new scope items that we take from our &#8216;product Backlog&#8217;.</p>
<p style="text-align: left;">We are currently running a one-hour planning session with the whole team every 2 weeks, which gives us ample time to review where we are with the existing work items and allows us to estimate how much new scope we can bit off to keep us occupied for the next 2 weeks.</p>
<p style="text-align: left;">This process is incredibly tranparent and efficient. The constant replanning and course correction means that: we rarely build anything that is not part of the final solution; everyone on the team is cross skilled and across the big picture; we can easily slot in refactoring tasks to increase the robustness of components we have already built but need some &#8216;love&#8217;; reporting upwards to management on progress is easy due to the high visibility of the methodology (lets face it - who could miss our scrum wall!).</p>
<p style="text-align: left;">The best thing about this methodology is that the team is completely behind it. The core team members don&#8217;t want to work without it and new recruits accept and join in with the processes eagerly.</p>
<p style="text-align: left;">LONG LIVE SCRUM!</p>
<p><a href="http://sharethis.com/item?&wp=2.7.1&amp;publisher=e7067adf-03c9-4684-bd43-845f964c4034&amp;title=Scrum+Secret+%232+-+low+tech+rocks%21&amp;url=http%3A%2F%2Fwww.buildmasters.com.au%2F2008%2F08%2F01%2Fa-victory-for-scrum%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.buildmasters.com.au/2008/08/01/a-victory-for-scrum/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
