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

<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>Mon, 15 Sep 2008 12:35:10 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<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[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 for now, using [...]<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>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.5.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[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 a simple pleasant [...]<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>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.5.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[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 20 years. DB2, [...]<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>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>LINQ: ditto.</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.5.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.5.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.5.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>
		<item>
		<title>Application virtualization with xenocode</title>
		<link>http://www.buildmasters.com.au/2008/07/14/application-virtualization/</link>
		<comments>http://www.buildmasters.com.au/2008/07/14/application-virtualization/#comments</comments>
		<pubDate>Mon, 14 Jul 2008 13:25:48 +0000</pubDate>
		<dc:creator>grendo</dc:creator>
		
		<category><![CDATA[Development]]></category>

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

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

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

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

		<guid isPermaLink="false">http://buildmasters.com.au/?p=55</guid>
		<description><![CDATA[Application is the future of virtualization.  Xenocode allows you to package up an application and deploy it in a virtaul exe to run anywhere, (anywhere on windows).  I came across it when I wanted to create a portable application using the ,net framework.  Xenocode is amazing.  It allowed me to package [...]<script type="text/javascript">SHARETHIS.addEntry({ title: "Application virtualization with xenocode", url: "http://www.buildmasters.com.au/2008/07/14/application-virtualization/" });</script>]]></description>
			<content:encoded><![CDATA[<p>Application is the future of virtualization.  Xenocode allows you to package up an application and deploy it in a virtaul exe to run anywhere, (anywhere on windows).  I came across it when I wanted to create a portable application using the ,net framework.  Xenocode is amazing.  It allowed me to package up a winform application written in C# to produce a stand alone exe that could run on any windows box even without the .net framework installed.  I have not tried it under wine/linux but it is on my todo list.</p>
<p>While we have yet to use it in a project think how easy a deployment process will be when have xcopy deployment without any need for a framework to be installed on the destination machine.</p>
<p>So for all you .net coders out there start pumping out the usb portable apps with visual studio.</p>
<p><a href="http://www.xenocode.com/">http://www.xenocode.com/</a></p>
<p>turn your dotnet exe into a portable usb app</p>
<p><a href="http://sharethis.com/item?&wp=2.5.1&amp;publisher=e7067adf-03c9-4684-bd43-845f964c4034&amp;title=Application+virtualization+with+xenocode&amp;url=http%3A%2F%2Fwww.buildmasters.com.au%2F2008%2F07%2F14%2Fapplication-virtualization%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.buildmasters.com.au/2008/07/14/application-virtualization/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Subversion</title>
		<link>http://www.buildmasters.com.au/2008/07/14/subversion/</link>
		<comments>http://www.buildmasters.com.au/2008/07/14/subversion/#comments</comments>
		<pubDate>Mon, 14 Jul 2008 11:53:52 +0000</pubDate>
		<dc:creator>grendo</dc:creator>
		
		<category><![CDATA[Development]]></category>

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

		<category><![CDATA[version control subversion tortisesvn]]></category>

		<guid isPermaLink="false">http://buildmasters.com.au/?p=67</guid>
		<description><![CDATA[Subversion is our prefered tool for version control.  With the latest version you have merge tracking and can compare history of word and excel documents, (when using the tortisesvn client).  With this new functionality I can see it being our document management system as well.  It is fast, easy to set up [...]<script type="text/javascript">SHARETHIS.addEntry({ title: "Subversion", url: "http://www.buildmasters.com.au/2008/07/14/subversion/" });</script>]]></description>
			<content:encoded><![CDATA[<p>Subversion is our prefered tool for version control.  With the latest version you have merge tracking and can compare history of word and excel documents, (when using the tortisesvn client).  With this new functionality I can see it being our document management system as well.  It is fast, easy to set up and transactional, (commits all your changes or none at all unlike pvcs).  As a added bonus it is opensource and free to use.</p>
<p><a href="http://subversion.tigris.org/">http://subversion.tigris.org/</a></p>
<p>There are many clients for subversion the two we prefer are</p>
<p><a href="http://tortoisesvn.tigris.org/">http://tortoisesvn.tigris.org/</a></p>
<p><a href="http://www.visualsvn.com/">http://www.visualsvn.com/</a></p>
<p>This is one of the core bits of software you want running on day one of a project.  We had a architecture team try to force us to use pvcs which is non transactional and pay for the privilege.  What a step backwards that would have been.  It was only that we had it running in our build process from day one that stopped this happening.  It was a bit of a lesson for me, if you want your key bits of technology supporting the development process have them running on day one.  I wish we did the same with our bug tracking tool.  Unfortunately we were forced to use trackrecord which I would not recommend to anyone, (especially when there are some many excellent open source bug tracking tools).</p>
<p><a href="http://sharethis.com/item?&wp=2.5.1&amp;publisher=e7067adf-03c9-4684-bd43-845f964c4034&amp;title=Subversion&amp;url=http%3A%2F%2Fwww.buildmasters.com.au%2F2008%2F07%2F14%2Fsubversion%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.buildmasters.com.au/2008/07/14/subversion/feed/</wfw:commentRss>
		</item>
		<item>
		<title>The New Developer</title>
		<link>http://www.buildmasters.com.au/2008/07/14/the-new-developer/</link>
		<comments>http://www.buildmasters.com.au/2008/07/14/the-new-developer/#comments</comments>
		<pubDate>Mon, 14 Jul 2008 11:31:53 +0000</pubDate>
		<dc:creator>grendo</dc:creator>
		
		<category><![CDATA[Development]]></category>

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

		<guid isPermaLink="false">http://buildmasters.com.au/?p=65</guid>
		<description><![CDATA[We believe that when a new developer starts work in our team they should be able to start work on real project tasks by lunch. To achieve this you need a number of things to be in place namely

A Buildprocess
Automated unit testing
Developers virtual image
Project tasks that can be allocated to a new developer
A developer allocated [...]<script type="text/javascript">SHARETHIS.addEntry({ title: "The New Developer", url: "http://www.buildmasters.com.au/2008/07/14/the-new-developer/" });</script>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.buildmasters.com.au/wp-content/uploads/2008/07/dilbert.jpg"><img class="alignnone size-medium wp-image-120" title="dilbert" src="http://www.buildmasters.com.au/wp-content/uploads/2008/07/dilbert-189x300.jpg" alt="" width="189" height="300" /></a>We believe that when a new developer starts work in our team they should be able to start work on real project tasks by lunch. To achieve this you need a number of things to be in place namely</p>
<ul>
<li>A Buildprocess</li>
<li>Automated unit testing</li>
<li>Developers virtual image</li>
<li>Project tasks that can be allocated to a new developer</li>
<li>A developer allocated to pair with the new developer in the initial stages.</li>
</ul>
<p>Added to this we have a number concepts to keep in mind</p>
<p><strong>Developers are drip fed into the team.</strong> New developers should be assimilated into the team one or two at a time. This is to avoid old school or negative views around the benefit of automated builds and unit testing. By having one or two developers come in at a time it is easy to get them coding and testing the way we want.</p>
<p><strong>Egoless programming</strong>. By this we mean no developer owns a specific piece of code and you should always be able to listen to a different view. Don&#8217;t be defensive when someone when someone offers a different approach to something. I have met very few developers I could not learn something from, (they do exist but usually will not fit into ego less programming because they have big ego&#8217;s).</p>
<p><strong>Everyone is Expendable.</strong> If you find someone in your team that can not be replaced easily start to arrange so their knowledge gets shared around. The reality of the IT industry is people change jobs all the time. The culture we have built up in our team has kept this to a minimum as everyone enjoys the success and development processes we follow. From a management point of view we have done a good job if on any given day we can loose an experienced resource and the team keeps working as usual.  Having one person own a price of code can have disastrous results. If one person is left to be the only developer on a piece of the application they generally fall back to their core skills to solve a problem. A recent example we encountered was when we inherited an etl process. We had no influence over the development and were lead to believe that ssis was used to implement it as prescribed by the project architecture. After we looked at the code we soon realized that just about all of the etl was implemented in tsql which was the developers primary skill. All the out of the box functionality which makes ssis a useful etl tool was ignored as it was not in the skill set of the developer. This left us with a very complex solution to something that should have been a lot easier if it was implemented by someone with ssis experience. In the end we had to make the call to rewrite the etl layer using ssis functionality and keeping the design simple.</p>
<p><strong>Be wary of people who tell you they are an architect every chance they get. </strong>While some architects are worth their weight in gold they are few and far between. Make sure you check out their cv references through people you know instead of who is on their cv. I onced asked a architect who was running a data warehouse project if their database was a typical data warehouse schema expecting something like start or snowflake schema but got <em>&#8220;Yes third normal form&#8221;</em>.</p>
<p><strong>Application support should be involved in the development process.</strong> Instead of getting new resourses it is better to get application support staff involved in the development process.  How better way to ensure your legacy of automated builds and deploys will be continued when the project moves into the application support phase.</p>
<p><strong>Keep It Simple</strong>. Every project is a battle to keep technology decisions simple. I have worked on very few large projects that have not been over engineered to some degree. You are always battling architecture groups, enterprise teams, empire builders and people who can talk well in meetings but are light on technical ability to implement a simple solution. You loose your fair share of these battles due to political influences. The only thing you can do in this case is to make sure you have a review at the end of the development cycle where you point out to upper management how a simple job was made complex to the detriment of the project. If you can hire someone off the street with 2+ years experience, they can sit down and understand your code, maintain it and deploy changes to production you have done your job.</p>
<p>So when a new developer arrives on site what happens first.  <strong>During their first hour</strong></p>
<ul>
<li>They meet the team during our morning 10 minute scrum.  During the meeting they are assign a task.</li>
<li>We pair a developer with them</li>
<li>They copy our developers vmware image to their computer</li>
<li>Start the developers image</li>
<li>Run a script to personalise the image</li>
<li>Start our build process and run the local clean step.  This will download the latest databases, code and binaries that successfuly built on the build machine, (compiled and pasted unit tests).</li>
</ul>
<p>The developer now has everything they need to complete their task and become a valued contributor to the team in no time at all.</p>
<p><a href="http://sharethis.com/item?&wp=2.5.1&amp;publisher=e7067adf-03c9-4684-bd43-845f964c4034&amp;title=The+New+Developer&amp;url=http%3A%2F%2Fwww.buildmasters.com.au%2F2008%2F07%2F14%2Fthe-new-developer%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.buildmasters.com.au/2008/07/14/the-new-developer/feed/</wfw:commentRss>
		</item>
		<item>
		<title>64 bit Windows: WTF: 64 bit dlls live in System32 dir, 32 bit dlls&#8217;s are in SysWow64</title>
		<link>http://www.buildmasters.com.au/2008/06/30/64-bit-windows-wtf-64-bit-dlls-live-in-system32-dir-32-bit-dllss-are-in-syswow64/</link>
		<comments>http://www.buildmasters.com.au/2008/06/30/64-bit-windows-wtf-64-bit-dlls-live-in-system32-dir-32-bit-dllss-are-in-syswow64/#comments</comments>
		<pubDate>Mon, 30 Jun 2008 11:39:35 +0000</pubDate>
		<dc:creator>tubby taylor</dc:creator>
		
		<category><![CDATA[Current Projects]]></category>

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

		<guid isPermaLink="false">http://www.buildmasters.com.au/?p=118</guid>
		<description><![CDATA[Here at Buildmasters, we have now moved all our development vm&#8217;s and other servers to 64 bit editions of Windows.
The 4GB memory limit is gone, and no more recycling IIS app pools and running out of virtual memory.
One thing to note however: The \System32 directory contains 64 bit dlls, and the legacy 32 bit emulation [...]<script type="text/javascript">SHARETHIS.addEntry({ title: "64 bit Windows: WTF: 64 bit dlls live in System32 dir, 32 bit dlls&#8217;s are in SysWow64", url: "http://www.buildmasters.com.au/2008/06/30/64-bit-windows-wtf-64-bit-dlls-live-in-system32-dir-32-bit-dllss-are-in-syswow64/" });</script>]]></description>
			<content:encoded><![CDATA[<p>Here at Buildmasters, we have now moved all our development vm&#8217;s and other servers to 64 bit editions of Windows.</p>
<p>The 4GB memory limit is gone, and no more recycling IIS app pools and running out of virtual memory.</p>
<p>One thing to note however: The \System32 directory contains 64 bit dlls, and the legacy 32 bit emulation dll&#8217;s live in the \SysWow64 directory.</p>
<p>The is all done for backwards compatibilty, but it is very confusing.</p>
<p>Have a look at <a href="http://en.wikipedia.org/wiki/WOW64">http://en.wikipedia.org/wiki/WOW64<br />
</a> for more info. </p>
<p><a href="http://sharethis.com/item?&wp=2.5.1&amp;publisher=e7067adf-03c9-4684-bd43-845f964c4034&amp;title=64+bit+Windows%3A+WTF%3A+64+bit+dlls+live+in+System32+dir%2C+32+bit+dlls%26%238217%3Bs+are+in+SysWow64&amp;url=http%3A%2F%2Fwww.buildmasters.com.au%2F2008%2F06%2F30%2F64-bit-windows-wtf-64-bit-dlls-live-in-system32-dir-32-bit-dllss-are-in-syswow64%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.buildmasters.com.au/2008/06/30/64-bit-windows-wtf-64-bit-dlls-live-in-system32-dir-32-bit-dllss-are-in-syswow64/feed/</wfw:commentRss>
		</item>
		<item>
		<title>SqlServer2005: Move From TSQL To SQLCLR And Save Your Project</title>
		<link>http://www.buildmasters.com.au/2008/06/24/sqlserver2005-move-from-tsql-to-sqlclr-and-save-your-project/</link>
		<comments>http://www.buildmasters.com.au/2008/06/24/sqlserver2005-move-from-tsql-to-sqlclr-and-save-your-project/#comments</comments>
		<pubDate>Tue, 24 Jun 2008 14:12:53 +0000</pubDate>
		<dc:creator>tubby taylor</dc:creator>
		
		<category><![CDATA[Cool Technology]]></category>

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

		<guid isPermaLink="false">http://www.buildmasters.com.au/?p=116</guid>
		<description><![CDATA[Many organisations have lots of business rules in TSQL stored procedures.
You&#8217;re right, that&#8217;s crazy but that&#8217;s what we see all the time, and our current project in Sydney, Australia using the Eagle PACE product is no different. Eagle PACE is an Opertaional Data Store for the financial services industry, in our case the Funds Management [...]<script type="text/javascript">SHARETHIS.addEntry({ title: "SqlServer2005: Move From TSQL To SQLCLR And Save Your Project", url: "http://www.buildmasters.com.au/2008/06/24/sqlserver2005-move-from-tsql-to-sqlclr-and-save-your-project/" });</script>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.buildmasters.com.au/wp-content/uploads/2008/06/sql-clr.jpg"><img class="alignnone size-medium wp-image-117" title="sql-clr" src="http://www.buildmasters.com.au/wp-content/uploads/2008/06/sql-clr.jpg" alt="" width="99" height="127" /></a>Many organisations have lots of business rules in TSQL stored procedures.<br />
You&#8217;re right, that&#8217;s crazy but that&#8217;s what we see all the time, and our current project in Sydney, Australia using the Eagle PACE product is no different. Eagle PACE is an Opertaional Data Store for the financial services industry, in our case the Funds Management sector. At it&#8217;s heart is an enterprise database with a relational data model appropriate to the industry, and is surrounded by data feed mechanisms which in basic terms are a series of Stored Procedures.</p>
<p>Whilst a TSQL stored procedure is good for simple logic, eg stringing together a couple of selects and inserts, it is simply not up to the task of handling complex business rules and workflow.</p>
<p>I would say that a TSQL stored proc of more than 200 lines is just to complex to debug, enhance and test.</p>
<p>TSQL falls short in the following areas:</p>
<p>1) Code reuse.<br />
There isn&#8217;t any.<br />
No classes, no rowtypes, no inheritance of stored procs or functions.<br />
No way to encapsulate functionality - the only way is, that&#8217;s right, you have to write another stored proc and have nested calls - yuk!<br />
Absolutely awesome when you have 133 parameters to pass around.<br />
[Dont laugh - we have this many parameters and more in the stored proc interfaces we have to maintain]<span id="more-116"></span></p>
<p>2) Error handling.<br />
SqlServer2005 has try/catch, which is good, but not yet widely used.<br />
Most TSQL code we see has lots of if/goto statements after each real code statment.<br />
This blows out the size of the proc and turns in into spaghetti.<br />
This kind of error handling is quite intrusive, so one loses track of what the storeed proc is actually doing due to all the eror handling code.</p>
<p>3) Testability and code coverage.<br />
It is hard to unit test and do code coverage on a large stored proc.<br />
You cannot break it down and test chunks of it in unit tests.</p>
<p>Here&#8217;s a scenario we see all the time.<br />
You&#8217;ve been handed a 2000 line stored proc and it has a bug or it needs an enhancement.<br />
There is no documentation of course, so to fix the problem you have to figure out what the hell it does, starting from the top and following the code paths until you find the problem.<br />
Oh dont forget all those goto error statements.<br />
Oops, I&#8217;ve just been distracted because the PA just walked past my desk, and I&#8217;ve lost my place somewhere in the bowels of this multi-page proc, so I have to start again at the top to figure out where I have to make the code fix.</p>
<p>At buildmasters, we were presented with several dozen very large TSQL stored procedures that were written in other countries [some of the worst TSQL code I have ever seen I must add] that we had to maintain and enhance [no documentaion provided of course]. All part of an Eagle PACE consulting enegagement in Sydney, Australia.<br />
These stored procs were unmaintainable.<br />
It was clear that we would not meet our development deadlines if we did not innovate at the TSQL level.<br />
Not only this, but the vendor&#8217;s product (Eagle PACE) could only talk to external components via ODBC, so refactoring into a C# or Java business layer was out of the question.</p>
<p>The innovation we came up with was to write/refactor all TSQL stored procedures and functions into C# SQLCLR.</p>
<p>Not only did we get to write business logic in C#, we were able to abstract much of the code into base classes and helper methods.<br />
This, together with the use of C# generics, nullable types and predictable try/catch error handling, meant that we wrote a lot less code.<br />
We literally reduced the code base by 1000&#8217;s of lines by moving from TSQL to SQLCLR.<br />
Less lines of code means less bugs, because, as we all know, coding is the art of inserting bugs into software.</p>
<p>Now, a new developer can approach an unfamiliar SQLCLR stored proc with confidence that he will be able to understand its purpose within a short time.<br />
Because common functionality is encapsulated in base classes and helper methods, a stored procedure&#8217;s code consists of only the specific business rules required for its purpose.<br />
It is much easier to find a bug or the place where an enhancement is to be performed.<br />
Error handling is consistemt and non-intrusive - just throw an exception and let the base class do the rest.<br />
Also, developers can unit test SQLCLR C# methods and base classes in isolation.</p>
<p>We also wrote a deployment tool that takes a C# SQLCLR assembly and registers the appropriate stored procedures and functions into the SqlServer database, so that as far as Eagle PACE is concerned, our SQLCLR stored procs appear as normal TSQL stored procs, happily callable from the vendor&#8217;s ODBC interface.<br />
We have innovated the Eagle in a way that has never been done before.</p>
<p>This is done automatically as part of our continuous build and deploy process, and all these C# SQLCLR stored procedures are subject to the same unit test code coverage as the rest of our code.</p>
<p>SQLCLR - really cool technology.</p>
<p><a href="http://sharethis.com/item?&wp=2.5.1&amp;publisher=e7067adf-03c9-4684-bd43-845f964c4034&amp;title=SqlServer2005%3A+Move+From+TSQL+To+SQLCLR+And+Save+Your+Project&amp;url=http%3A%2F%2Fwww.buildmasters.com.au%2F2008%2F06%2F24%2Fsqlserver2005-move-from-tsql-to-sqlclr-and-save-your-project%2F">ShareThis</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.buildmasters.com.au/2008/06/24/sqlserver2005-move-from-tsql-to-sqlclr-and-save-your-project/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
