<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" version="2.0">
  <channel>
    <title>Michael Maddox - Software Development - LinqToSql</title>
    <link>http://www.capprime.com/software_development_weblog/</link>
    <description>Best Practices, Knowlegde Base Type Articles, General Tech Opinions, etc.</description>
    <language>en-us</language>
    <copyright>Michael Maddox</copyright>
    <lastBuildDate>Thu, 24 Sep 2009 08:53:46 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.3.9074.18820</generator>
    <managingEditor>Michael.P.Maddox@gmail.com</managingEditor>
    <webMaster>Michael.P.Maddox@gmail.com</webMaster>
    <item>
      <trackback:ping>http://www.capprime.com/software_development_weblog/Trackback.aspx?guid=162facaa-a3b9-4dc5-b770-657e27e887ad</trackback:ping>
      <pingback:server>http://www.capprime.com/software_development_weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.capprime.com/software_development_weblog/PermaLink,guid,162facaa-a3b9-4dc5-b770-657e27e887ad.aspx</pingback:target>
      <dc:creator>Michael Maddox</dc:creator>
      <wfw:comment>http://www.capprime.com/software_development_weblog/CommentView,guid,162facaa-a3b9-4dc5-b770-657e27e887ad.aspx</wfw:comment>
      <wfw:commentRss>http://www.capprime.com/software_development_weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=162facaa-a3b9-4dc5-b770-657e27e887ad</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
As of 08/01/2010, this post has been rewritten and is now available here:
</p>
        <p>
          <a href="http://www.capprime.com/software_development_weblog/PermaLink,guid,d404eb9a-57bf-46e0-976a-9f81312ef5a8.aspx">http://www.capprime.com/software_development_weblog/PermaLink,guid,d404eb9a-57bf-46e0-976a-9f81312ef5a8.aspx</a>
        </p>
        <p>
ActiveWriter was replaced in the sample with the <a href="http://www.agilityfororms.com/Home/Products/AfoCastleActiveRecordModelCodeGenerator/">Agility
for ORMs Castle ActiveRecord code generator</a> (which I wrote) which generates higher
quality Castle ActiveRecord code which results in a much smoother development process
and a production worthy result.
</p>
        <p>
The unedited original post follows:
</p>
        <p>
--
</p>
        <p>
NHibernate is a great ORM.  It's mature.  It's feature rich.  It's
free.  Source code is available if necessary.
</p>
        <p>
It now also supports Linq and Linq is great!
</p>
        <p>
This is a quick guide to getting up and running with NHibernate and Linq quickly. 
The overall experience feels vaguely similar to LinqToSql, without all the <a href="http://www.capprime.com/software_development_weblog/PermaLink,guid,78e9dd46-b743-4d10-a541-2593354028ba.aspx">drawbacks</a> and
lock-in of LinqToSql.
</p>
        <p>
We are going to assume our database already exists.  We are going to assume that
database is Northwind, and we are going to assume that we are doing database driven
design (as opposed to domain driven design).  Northwind setup is described below.
</p>
        <p>
We are going to use Visual Studio 2008 with Service Pack 1 and SQL Server 2008 Express. 
(Note: I'm not sure if everything here will work with Visual Web Developer 2008 Express
Edition (a completely free stack).  I have Visual Web Developer 2008 Express
Edition installed, but I'm not sure if the Active Writer install will work with it
since the file type isn't showing up for me.)
</p>
        <p>
To speed the process along, we are going to use <a href="http://www.castleproject.org/activerecord/index.html">Castle
Active Record</a> to implement a basic <a href="http://en.wikipedia.org/wiki/Active_record_pattern">Active
Record pattern</a>.
</p>
        <p>
This means we won't be using NHibernate's famous XML mapping files.
</p>
        <p>
And to really speed things along, we are going to use <a href="http://using.castleproject.org/display/Contrib/ActiveWriter">Castle
ActiveWriter</a> to get some basic Active Record code generation.
</p>
        <p>
While I wouldn't necessarily use this stack for a production application, it's a very
quick way to get up and running.  This example is built on NHibernate and so
all that goodness is still available later when necessary.  You aren't really
tied to any proprietary or inflexible features.
</p>
        <p>
          <br />
Step 1:
</p>
        <p>
Download and install ActiveWriter on top of VS 2008.  The download link is available
from here:
</p>
        <p>
          <a href="http://using.castleproject.org/display/Contrib/ActiveWriter">http://using.castleproject.org/display/Contrib/ActiveWriter</a>
        </p>
        <p>
At the time of writing, the current version is "Preview 4.1 (26/06/2008)".
</p>
        <p>
I rebooted after the install since I have been burned one too many times, but rebooting
is possibly not necessary.
</p>
        <p>
          <br />
Step 2:
</p>
        <p>
Next, we will download and install the Northwind database.
</p>
        <p>
Jeff Atwood provides approximate instructions here (ask specific questions in the
comments if you get stuck):
</p>
        <p>
          <a href="http://www.codinghorror.com/blog/archives/000434.html">http://www.codinghorror.com/blog/archives/000434.html</a>
        </p>
        <p>
Follow the path for installing the binary files from the command line.  I have
tested that the SQL 2005 instructions work on SQL 2008.
</p>
        <p>
          <br />
Step 3:
</p>
        <p>
Download Castle Active Record:
</p>
        <p>
          <a href="http://www.castleproject.org/castle/download.html">http://www.castleproject.org/castle/download.html</a>
        </p>
        <p>
At the time of writing, the current version is "ActiveRecord 2.0 - August 1st, 2009". 
Unzip it and remember where you put it, you'll need that info in the next step.
</p>
        <p>
          <br />
Step 4:
</p>
        <p>
Start Visual Studio 2008
</p>
        <p>
We will create a new console application project:
</p>
        <p>
File -&gt; New -&gt; Project<br />
 Visual C# -&gt; Windows -&gt; Console Application<br />
  ConsoleApplication1 -&gt; OK
</p>
        <p>
We need to add the appropriate NHibernate &amp; Castle Active Record references:
</p>
        <p>
Solution Explorer<br />
 Right Click ConsoleApplication1 -&gt; References -&gt; Add<br />
  Browse Tab<br />
   Go to your Castle ActiveRecord 2.0 download location and add:<br />
    Castle.ActiveRecord.dll<br />
    Castle.DynamicProxy2.dll<br />
    NHibernate.dll<br />
    NHibernate.Linq.dll<br />
   Click OK
</p>
        <p>
And add a reference to System.Configuration as well:
</p>
        <p>
Solution Explorer<br />
 Right Click ConsoleApplication1 -&gt; References -&gt; Add<br />
  .NET Tab<br />
   System.Configuration<br />
  Click OK
</p>
        <p>
          <br />
Step 5:
</p>
        <p>
We will add the ActiveWriter1.actiw files to the project:
</p>
        <p>
Solution Explorer<br />
 Right Click ConsoleApplication1 -&gt; Add -&gt; New Item...<br />
  Visual C# Items -&gt; ActiveWriter (it's at the bottom of the list for
me)<br />
  Add
</p>
        <p>
Click OK on the Security Warning
</p>
        <p>
Close the class details window
</p>
        <p>
          <br />
Step 6:
</p>
        <p>
We will find the Northwind database in the Server Explorer:
</p>
        <p>
View -&gt; Server Explorer<br />
 Data Connections -&gt; Add Connection...<br />
  Choose your Server name<br />
  Choose the correct login info<br />
  Select "Northwind" as the database<br />
  Click "Test Connection"<br />
  Assuming that succeeds, click OK<br />
 Expand the Northwind Tables node<br />
 Now drag and drop the following tables to the Active Writer Designer surface:<br />
  Orders<br />
  Shippers
</p>
        <p>
Save the ActiveWriter1.actiw file<br />
Click OK on the Security Warning<br />
Close the ActiveWriter1.actiw file
</p>
        <p>
You can look through the new ActiveWriter1.cs file in Solution Explorer to see the
generated classes we are going to use later.
</p>
        <p>
          <br />
Step 7:
</p>
        <p>
We will now add an Application Configuration File to the project and put the Northwind
Connection String into it:
</p>
        <p>
Solution Explorer<br />
 Right Click ConsoleApplication1 -&gt; Add -&gt; New Item...<br />
  Visual C# Items -&gt; General -&gt; Application Configuration File<br />
  Add
</p>
        <p>
Modify the file to look like this and use your specific DB connection info:
</p>
        <p>
--<br />
&lt;?xml version="1.0" encoding="utf-8" ?&gt;<br />
&lt;configuration&gt;<br />
  &lt;connectionStrings&gt;<br />
    &lt;add name="Northwind" connectionString="Data Source=ServerName;Initial
Catalog=Northwind;User ID=sa;Password=password;"/&gt;<br />
  &lt;/connectionStrings&gt;<br />
&lt;/configuration&gt;<br />
--
</p>
        <p>
          <br />
Step 8:
</p>
        <p>
Open the main "Program.cs" class and add the following new methods:
</p>
        <p>
        private static void InitializeNHibernateActiveRecord()<br />
        {<br />
            string connectionString
= System.Configuration.ConfigurationManager.ConnectionStrings["Northwind"].ToString();<br />
            InPlaceConfigurationSource
configuration = InPlaceConfigurationSource.Build(DatabaseType.MSSQLServer2005, connectionString);
</p>
        <p>
            ActiveRecordStarter.Initialize(configuration,<br />
               
typeof(Orders),<br />
               
typeof(Shippers)<br />
               
);<br />
        }
</p>
        <p>
        private static ISession CreateNHibernateActiveRecordSession()<br />
        {<br />
            // This uses the
values setup during ActiveRecordStarter.Initialize() to configure and create the session<br />
            return ActiveRecordMediator.GetSessionFactoryHolder().CreateSession(typeof(ActiveRecordBase));<br />
        }
</p>
        <p>
Add the following code to the Main Method:
</p>
        <p>
        static void Main(string[] args)<br />
        {<br />
            try<br />
            {<br />
               
InitializeNHibernateActiveRecord();
</p>
        <p>
               
using (ISession dbSession = CreateNHibernateActiveRecordSession())<br />
               
{<br />
                   
var queryToExecute = from oneShippers in dbSession.Linq&lt;Shippers&gt;()<br />
                                        
select oneShippers;
</p>
        <p>
                   
foreach (Shippers oneShipper in queryToExecute.ToList())<br />
                   
{<br />
                       
Console.WriteLine("oneShipper ShipperID=[" + oneShipper.ShipperID + "] CompanyName=["
+ oneShipper.CompanyName + "]");<br />
                   
}               
}<br />
            }<br />
            catch (Exception
oneException)<br />
            {<br />
               
Console.WriteLine("oneException=[" + oneException + "]");<br />
               
throw; // you can remove this if you'd rather the program exit "more normally"<br />
            }<br />
        }
</p>
        <p>
Add the following using statements at the top of Program.cs:
</p>
        <p>
using Castle.ActiveRecord;<br />
using Castle.ActiveRecord.Framework.Config;
</p>
        <p>
using NHibernate;<br />
using NHibernate.Linq;
</p>
        <p>
          <br />
Step 9:
</p>
        <p>
Copy the NHibernate.ByteCode.Castle.dll file from your Castle Active Record download
unzip directory to your projects bin\Debug\ folder.
</p>
        <p>
          <br />
Step 10:
</p>
        <p>
Run the application:
</p>
        <p>
Ctrl-F5 (Debug -&gt; Start Without Debugging)
</p>
        <p>
And you should see the following output:
</p>
        <p>
--<br />
oneShipper ShipperID=[1] CompanyName=[Speedy Express]<br />
oneShipper ShipperID=[2] CompanyName=[United Package]<br />
oneShipper ShipperID=[3] CompanyName=[Federal Shipping]<br />
Press any key to continue . . .<br />
--
</p>
        <p>
So, the basics are working.
</p>
        <p>
I would have loved to show some Order Details instead of Shippers, but there appear
to be a lot of complexities with the Northwind database that don't seem to work well
with the current release versions of ActiveWriter / ActiveRecord.  Hopefully
those issues will be fixed over time.
</p>
        <p>
          <br />
Step 11:
</p>
        <p>
Now let's do a query which requires a join.
</p>
        <p>
The CustomerID field on the Orders class first needs to have it's column type changed
for it to work.
</p>
        <p>
(Re)open the ActiveWriter1.actiw file.
</p>
        <p>
Right Click on Orders -&gt; CustomerID -&gt; Properties<br />
 Set the Column Type to String
</p>
        <p>
          <br />
Step 12:
</p>
        <p>
Let's model the relationship between Orders and Shippers in the Designer.
</p>
        <p>
The foreign key relationship is Orders.ShipVia &lt;-&gt; Shippers.ShipperID, with
one shipper having 0 to many orders.
</p>
        <p>
With the ActiveWriter1.actiw designer open, go to the toolbox (View -&gt; Toolbox).
</p>
        <p>
Select the "Many To One Relationship" option under "ActiveWriter".
</p>
        <p>
Click (and hold the click) on the Orders table and drag the line onto the Shippers
table.
</p>
        <p>
Highlight the line between the two tables and right click -&gt; Properties.
</p>
        <p>
Set the Source Column to ShipVia<br />
Set the Target Table to Orders
</p>
        <p>
          <br />
Step 13:
</p>
        <p>
Let's add a Linq query to the Main method for Orders to exercise that new relationship:
</p>
        <p>
                   
var queryToExecute = from oneOrders in dbSession.Linq&lt;Orders&gt;()<br />
                                        
select oneOrders;
</p>
        <p>
                   
foreach (Orders oneOrder in queryToExecute.ToList())<br />
                   
{<br />
                       
Console.WriteLine("oneOrder OrderID=[" + oneOrder.OrderID + "] ShipVia=[" + oneOrder.ShipVia
+ "] Shippers.CompanyName=[" + oneOrder.Shippers.CompanyName + "]");<br />
                   
}
</p>
        <p>
          <br />
Step 14:
</p>
        <p>
Run the application:
</p>
        <p>
Ctrl-F5 (Debug -&gt; Start Without Debugging)
</p>
        <p>
And you should see the following output:
</p>
        <p>
--<br />
oneOrder OrderID=[10248] ShipVia=[3] Shippers.CompanyName=[Federal Shipping]<br />
oneOrder OrderID=[10249] ShipVia=[1] Shippers.CompanyName=[Speedy Express]
</p>
        <p>
&lt;snip&gt;
</p>
        <p>
oneOrder OrderID=[11076] ShipVia=[2] Shippers.CompanyName=[United Package]<br />
oneOrder OrderID=[11077] ShipVia=[2] Shippers.CompanyName=[United Package]<br />
--
</p>
        <p>
          <br />
We have successfully executed a join query through Linq.
</p>
        <p>
I was somewhat surprised when I found out this was running 4 queries under the covers. 
Basically:
</p>
        <p>
SELECT Orders.*, Shippers.* FROM Orders LEFT OUTER JOIN Shippers ON Orders.ShipVia
= Shippers.ShipperID<br />
SELECT * FROM Orders WHERE ShipVia = 2<br />
SELECT * FROM Orders WHERE ShipVia = 1<br />
SELECT * FROM Orders WHERE ShipVia = 3
</p>
        <p>
I either expected 1 query (eager fetch) or 831 queries (lazy fetch - 1 query for the
list of orders + 1 query for each order to get the Shipper Company Name).
</p>
        <p>
The results of first query contain enough information to display what the code is
asking for, so it's definitely eager fetch behavior.
</p>
        <p>
Changing the code to only print OrderID does not appear to change which queries are
run.
</p>
        <p>
So don't necessarily make assumptions about how your ORM is going to be generating
queries under the covers, especially if performance seems to be an issue when it shouldn't
be.
</p>
        <p>
          <br />
Some additional things to note:
</p>
        <p>
Castle ActiveRecord provides an ActiveRecordLinq.AsQueryable method that would appear
to be useable in place of the ISession.Linq method (with a call to new up a SessionScope
instead of calling CreateSession), but I couldn't get that to work (I didn't dig into
it).
</p>
        <p>
While the code sample above makes for a decent demo and a quick start, your mileage
will likely vary.  When things work great, they work great.  This sample
didn't end up being as I planned though because I had to work around / avoid things
that I couldn't easily get to work (like Order Details).  In the end, I am very
satisfied that the code sample is pretty short and straight-forward, yet so much power
is happening behind the scenes.
</p>
        <p>
NHibernate supports pretty much all the weirdness your database needs, but ActiveRecord
supports less weirdness, and ActiveWriter supports even less.  The higher up
the stack/abstraction you get, the more likely edge cases haven't been tested/implemented
yet.
</p>
        <p>
Now that you have the basic NHibernate Linq infrastructure in place, there are plenty
of Linq examples and sample code available elsewhere.
</p>
        <p>
Enjoy!
</p>
        <img width="0" height="0" src="http://www.capprime.com/software_development_weblog/aggbug.ashx?id=162facaa-a3b9-4dc5-b770-657e27e887ad" />
      </body>
      <title>Using Linq with NHibernate : A Quick Start</title>
      <guid isPermaLink="false">http://www.capprime.com/software_development_weblog/PermaLink,guid,162facaa-a3b9-4dc5-b770-657e27e887ad.aspx</guid>
      <link>http://www.capprime.com/software_development_weblog/2009/09/24/UsingLinqWithNHibernateAQuickStart.aspx</link>
      <pubDate>Thu, 24 Sep 2009 08:53:46 GMT</pubDate>
      <description>&lt;p&gt;
As of 08/01/2010, this post has been rewritten and is now available here:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.capprime.com/software_development_weblog/PermaLink,guid,d404eb9a-57bf-46e0-976a-9f81312ef5a8.aspx"&gt;http://www.capprime.com/software_development_weblog/PermaLink,guid,d404eb9a-57bf-46e0-976a-9f81312ef5a8.aspx&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
ActiveWriter was replaced in the sample with the &lt;a href="http://www.agilityfororms.com/Home/Products/AfoCastleActiveRecordModelCodeGenerator/"&gt;Agility
for ORMs Castle ActiveRecord code generator&lt;/a&gt; (which I wrote) which generates higher
quality Castle ActiveRecord code which results in a much smoother development process
and a production worthy result.
&lt;/p&gt;
&lt;p&gt;
The unedited original post follows:
&lt;/p&gt;
&lt;p&gt;
--
&lt;/p&gt;
&lt;p&gt;
NHibernate is a great ORM.&amp;nbsp; It's mature.&amp;nbsp; It's feature rich.&amp;nbsp; It's
free.&amp;nbsp; Source code is available if necessary.
&lt;/p&gt;
&lt;p&gt;
It now also supports Linq and Linq is great!
&lt;/p&gt;
&lt;p&gt;
This is a quick guide to getting up and running with NHibernate and Linq quickly.&amp;nbsp;
The overall experience feels vaguely similar to LinqToSql, without all the &lt;a href="http://www.capprime.com/software_development_weblog/PermaLink,guid,78e9dd46-b743-4d10-a541-2593354028ba.aspx"&gt;drawbacks&lt;/a&gt; and
lock-in of LinqToSql.
&lt;/p&gt;
&lt;p&gt;
We are going to assume our database already exists.&amp;nbsp; We are going to assume that
database is Northwind, and we are going to assume that we are doing database driven
design (as opposed to domain driven design).&amp;nbsp; Northwind setup is described below.
&lt;/p&gt;
&lt;p&gt;
We are going to use Visual Studio 2008 with Service Pack 1 and SQL Server 2008 Express.&amp;nbsp;
(Note: I'm not sure if everything here will work with Visual Web Developer 2008 Express
Edition (a completely free stack).&amp;nbsp; I have Visual Web Developer 2008 Express
Edition installed, but I'm not sure if the Active Writer install will work with it
since the file type isn't showing up for me.)
&lt;/p&gt;
&lt;p&gt;
To speed the process along, we are going to use &lt;a href="http://www.castleproject.org/activerecord/index.html"&gt;Castle
Active Record&lt;/a&gt; to implement a basic &lt;a href="http://en.wikipedia.org/wiki/Active_record_pattern"&gt;Active
Record pattern&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
This means we won't be using NHibernate's famous XML mapping files.
&lt;/p&gt;
&lt;p&gt;
And to really speed things along, we are going to use &lt;a href="http://using.castleproject.org/display/Contrib/ActiveWriter"&gt;Castle
ActiveWriter&lt;/a&gt; to get some basic Active Record code generation.
&lt;/p&gt;
&lt;p&gt;
While I wouldn't necessarily use this stack for a production application, it's a very
quick way to get up and running.&amp;nbsp; This example is built on NHibernate and so
all that goodness is still available later when necessary.&amp;nbsp; You aren't really
tied to any proprietary or inflexible features.
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
Step 1:
&lt;/p&gt;
&lt;p&gt;
Download and install ActiveWriter on top of VS 2008.&amp;nbsp; The download link is available
from here:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://using.castleproject.org/display/Contrib/ActiveWriter"&gt;http://using.castleproject.org/display/Contrib/ActiveWriter&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
At the time of writing, the current version is "Preview 4.1 (26/06/2008)".
&lt;/p&gt;
&lt;p&gt;
I rebooted after the install since I have been burned one too many times, but rebooting
is possibly not necessary.
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
Step 2:
&lt;/p&gt;
&lt;p&gt;
Next, we will download and install the Northwind database.
&lt;/p&gt;
&lt;p&gt;
Jeff Atwood provides approximate instructions here (ask specific questions in the
comments if you get stuck):
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.codinghorror.com/blog/archives/000434.html"&gt;http://www.codinghorror.com/blog/archives/000434.html&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Follow the path for installing the binary files from the command line.&amp;nbsp; I have
tested that the SQL 2005 instructions work on SQL 2008.
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
Step 3:
&lt;/p&gt;
&lt;p&gt;
Download Castle Active Record:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.castleproject.org/castle/download.html"&gt;http://www.castleproject.org/castle/download.html&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
At the time of writing, the current version is "ActiveRecord 2.0 - August 1st, 2009".&amp;nbsp;
Unzip it and remember where you put it, you'll need that info in the next step.
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
Step 4:
&lt;/p&gt;
&lt;p&gt;
Start Visual Studio 2008
&lt;/p&gt;
&lt;p&gt;
We will create a new console application project:
&lt;/p&gt;
&lt;p&gt;
File -&amp;gt; New -&amp;gt; Project&lt;br&gt;
&amp;nbsp;Visual C# -&amp;gt; Windows -&amp;gt; Console Application&lt;br&gt;
&amp;nbsp;&amp;nbsp;ConsoleApplication1 -&amp;gt; OK
&lt;/p&gt;
&lt;p&gt;
We need to add the appropriate NHibernate &amp;amp; Castle Active Record references:
&lt;/p&gt;
&lt;p&gt;
Solution Explorer&lt;br&gt;
&amp;nbsp;Right Click ConsoleApplication1 -&amp;gt; References -&amp;gt; Add&lt;br&gt;
&amp;nbsp;&amp;nbsp;Browse Tab&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;Go to your Castle ActiveRecord 2.0 download location and add:&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Castle.ActiveRecord.dll&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Castle.DynamicProxy2.dll&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NHibernate.dll&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NHibernate.Linq.dll&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;Click OK
&lt;/p&gt;
&lt;p&gt;
And add a reference to System.Configuration as well:
&lt;/p&gt;
&lt;p&gt;
Solution Explorer&lt;br&gt;
&amp;nbsp;Right Click ConsoleApplication1 -&amp;gt; References -&amp;gt; Add&lt;br&gt;
&amp;nbsp;&amp;nbsp;.NET Tab&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;System.Configuration&lt;br&gt;
&amp;nbsp;&amp;nbsp;Click OK
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
Step 5:
&lt;/p&gt;
&lt;p&gt;
We will add the ActiveWriter1.actiw files to the project:
&lt;/p&gt;
&lt;p&gt;
Solution Explorer&lt;br&gt;
&amp;nbsp;Right Click ConsoleApplication1 -&amp;gt; Add -&amp;gt; New Item...&lt;br&gt;
&amp;nbsp;&amp;nbsp;Visual C# Items -&amp;gt; ActiveWriter (it's at the bottom of the list for
me)&lt;br&gt;
&amp;nbsp;&amp;nbsp;Add
&lt;/p&gt;
&lt;p&gt;
Click OK on the Security Warning
&lt;/p&gt;
&lt;p&gt;
Close the class details window
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
Step 6:
&lt;/p&gt;
&lt;p&gt;
We will find the Northwind database in the Server Explorer:
&lt;/p&gt;
&lt;p&gt;
View -&amp;gt; Server Explorer&lt;br&gt;
&amp;nbsp;Data Connections -&amp;gt; Add Connection...&lt;br&gt;
&amp;nbsp;&amp;nbsp;Choose your Server name&lt;br&gt;
&amp;nbsp;&amp;nbsp;Choose the correct login info&lt;br&gt;
&amp;nbsp;&amp;nbsp;Select "Northwind" as the database&lt;br&gt;
&amp;nbsp;&amp;nbsp;Click "Test Connection"&lt;br&gt;
&amp;nbsp;&amp;nbsp;Assuming that succeeds, click OK&lt;br&gt;
&amp;nbsp;Expand the Northwind Tables node&lt;br&gt;
&amp;nbsp;Now drag and drop the following tables to the Active Writer Designer surface:&lt;br&gt;
&amp;nbsp;&amp;nbsp;Orders&lt;br&gt;
&amp;nbsp;&amp;nbsp;Shippers
&lt;/p&gt;
&lt;p&gt;
Save the ActiveWriter1.actiw file&lt;br&gt;
Click OK on the Security Warning&lt;br&gt;
Close the ActiveWriter1.actiw file
&lt;/p&gt;
&lt;p&gt;
You can look through the new ActiveWriter1.cs file in Solution Explorer to see the
generated classes we are going to use later.
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
Step 7:
&lt;/p&gt;
&lt;p&gt;
We will now add an Application Configuration File to the project and put the Northwind
Connection String into it:
&lt;/p&gt;
&lt;p&gt;
Solution Explorer&lt;br&gt;
&amp;nbsp;Right Click ConsoleApplication1 -&amp;gt; Add -&amp;gt; New Item...&lt;br&gt;
&amp;nbsp;&amp;nbsp;Visual C# Items -&amp;gt; General -&amp;gt; Application Configuration File&lt;br&gt;
&amp;nbsp;&amp;nbsp;Add
&lt;/p&gt;
&lt;p&gt;
Modify the file to look like this and use your specific DB connection info:
&lt;/p&gt;
&lt;p&gt;
--&lt;br&gt;
&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;&lt;br&gt;
&amp;lt;configuration&amp;gt;&lt;br&gt;
&amp;nbsp; &amp;lt;connectionStrings&amp;gt;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;add name="Northwind" connectionString="Data Source=ServerName;Initial
Catalog=Northwind;User ID=sa;Password=password;"/&amp;gt;&lt;br&gt;
&amp;nbsp; &amp;lt;/connectionStrings&amp;gt;&lt;br&gt;
&amp;lt;/configuration&amp;gt;&lt;br&gt;
--
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
Step 8:
&lt;/p&gt;
&lt;p&gt;
Open the main "Program.cs" class and add the following new methods:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static void InitializeNHibernateActiveRecord()&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; string connectionString
= System.Configuration.ConfigurationManager.ConnectionStrings["Northwind"].ToString();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; InPlaceConfigurationSource
configuration = InPlaceConfigurationSource.Build(DatabaseType.MSSQLServer2005, connectionString);
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ActiveRecordStarter.Initialize(configuration,&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
typeof(Orders),&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
typeof(Shippers)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
);&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private static ISession CreateNHibernateActiveRecordSession()&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // This uses the
values setup during ActiveRecordStarter.Initialize() to configure and create the session&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return ActiveRecordMediator.GetSessionFactoryHolder().CreateSession(typeof(ActiveRecordBase));&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p&gt;
Add the following code to the Main Method:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void Main(string[] args)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
InitializeNHibernateActiveRecord();
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
using (ISession dbSession = CreateNHibernateActiveRecordSession())&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
var queryToExecute = from oneShippers in dbSession.Linq&amp;lt;Shippers&amp;gt;()&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
select oneShippers;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
foreach (Shippers oneShipper in queryToExecute.ToList())&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
Console.WriteLine("oneShipper ShipperID=[" + oneShipper.ShipperID + "] CompanyName=["
+ oneShipper.CompanyName + "]");&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch (Exception
oneException)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
Console.WriteLine("oneException=[" + oneException + "]");&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
throw; // you can remove this if you'd rather the program exit "more normally"&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&lt;/p&gt;
&lt;p&gt;
Add the following using statements at the top of Program.cs:
&lt;/p&gt;
&lt;p&gt;
using Castle.ActiveRecord;&lt;br&gt;
using Castle.ActiveRecord.Framework.Config;
&lt;/p&gt;
&lt;p&gt;
using NHibernate;&lt;br&gt;
using NHibernate.Linq;
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
Step 9:
&lt;/p&gt;
&lt;p&gt;
Copy the NHibernate.ByteCode.Castle.dll file from your Castle Active Record download
unzip directory to your projects bin\Debug\ folder.
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
Step 10:
&lt;/p&gt;
&lt;p&gt;
Run the application:
&lt;/p&gt;
&lt;p&gt;
Ctrl-F5 (Debug -&amp;gt; Start Without Debugging)
&lt;/p&gt;
&lt;p&gt;
And you should see the following output:
&lt;/p&gt;
&lt;p&gt;
--&lt;br&gt;
oneShipper ShipperID=[1] CompanyName=[Speedy Express]&lt;br&gt;
oneShipper ShipperID=[2] CompanyName=[United Package]&lt;br&gt;
oneShipper ShipperID=[3] CompanyName=[Federal Shipping]&lt;br&gt;
Press any key to continue . . .&lt;br&gt;
--
&lt;/p&gt;
&lt;p&gt;
So, the basics are working.
&lt;/p&gt;
&lt;p&gt;
I would have loved to show some Order Details instead of Shippers, but there appear
to be a lot of complexities with the Northwind database that don't seem to work well
with the current release versions of ActiveWriter / ActiveRecord.&amp;nbsp; Hopefully
those issues will be fixed over time.
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
Step 11:
&lt;/p&gt;
&lt;p&gt;
Now let's do a query which requires a join.
&lt;/p&gt;
&lt;p&gt;
The CustomerID field on the Orders class first needs to have it's column type changed
for it to work.
&lt;/p&gt;
&lt;p&gt;
(Re)open the ActiveWriter1.actiw file.
&lt;/p&gt;
&lt;p&gt;
Right Click on Orders -&amp;gt; CustomerID -&amp;gt; Properties&lt;br&gt;
&amp;nbsp;Set the Column Type to String
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
Step 12:
&lt;/p&gt;
&lt;p&gt;
Let's model the relationship between Orders and Shippers in the Designer.
&lt;/p&gt;
&lt;p&gt;
The foreign key relationship is Orders.ShipVia &amp;lt;-&amp;gt; Shippers.ShipperID, with
one shipper having 0 to many orders.
&lt;/p&gt;
&lt;p&gt;
With the ActiveWriter1.actiw designer open, go to the toolbox (View -&amp;gt; Toolbox).
&lt;/p&gt;
&lt;p&gt;
Select the "Many To One Relationship" option under "ActiveWriter".
&lt;/p&gt;
&lt;p&gt;
Click (and hold the click) on the Orders table and drag the line onto the Shippers
table.
&lt;/p&gt;
&lt;p&gt;
Highlight the line between the two tables and right click -&amp;gt; Properties.
&lt;/p&gt;
&lt;p&gt;
Set the Source Column to ShipVia&lt;br&gt;
Set the Target Table to Orders
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
Step 13:
&lt;/p&gt;
&lt;p&gt;
Let's add a Linq query to the Main method for Orders to exercise that new relationship:
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
var queryToExecute = from oneOrders in dbSession.Linq&amp;lt;Orders&amp;gt;()&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
select oneOrders;
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
foreach (Orders oneOrder in queryToExecute.ToList())&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
Console.WriteLine("oneOrder OrderID=[" + oneOrder.OrderID + "] ShipVia=[" + oneOrder.ShipVia
+ "] Shippers.CompanyName=[" + oneOrder.Shippers.CompanyName + "]");&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
}
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
Step 14:
&lt;/p&gt;
&lt;p&gt;
Run the application:
&lt;/p&gt;
&lt;p&gt;
Ctrl-F5 (Debug -&amp;gt; Start Without Debugging)
&lt;/p&gt;
&lt;p&gt;
And you should see the following output:
&lt;/p&gt;
&lt;p&gt;
--&lt;br&gt;
oneOrder OrderID=[10248] ShipVia=[3] Shippers.CompanyName=[Federal Shipping]&lt;br&gt;
oneOrder OrderID=[10249] ShipVia=[1] Shippers.CompanyName=[Speedy Express]
&lt;/p&gt;
&lt;p&gt;
&amp;lt;snip&amp;gt;
&lt;/p&gt;
&lt;p&gt;
oneOrder OrderID=[11076] ShipVia=[2] Shippers.CompanyName=[United Package]&lt;br&gt;
oneOrder OrderID=[11077] ShipVia=[2] Shippers.CompanyName=[United Package]&lt;br&gt;
--
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
We have successfully executed a join query through Linq.
&lt;/p&gt;
&lt;p&gt;
I was somewhat surprised when I found out this was running 4 queries under the covers.&amp;nbsp;
Basically:
&lt;/p&gt;
&lt;p&gt;
SELECT Orders.*, Shippers.* FROM Orders LEFT OUTER JOIN Shippers ON Orders.ShipVia
= Shippers.ShipperID&lt;br&gt;
SELECT * FROM Orders WHERE ShipVia = 2&lt;br&gt;
SELECT * FROM Orders WHERE ShipVia = 1&lt;br&gt;
SELECT * FROM Orders WHERE ShipVia = 3
&lt;/p&gt;
&lt;p&gt;
I either expected 1 query (eager fetch) or 831 queries (lazy fetch - 1 query for the
list of orders + 1 query for each order to get the Shipper Company Name).
&lt;/p&gt;
&lt;p&gt;
The results of first query contain enough information to display what the code is
asking for, so it's definitely eager fetch behavior.
&lt;/p&gt;
&lt;p&gt;
Changing the code to only print OrderID does not appear to change which queries are
run.
&lt;/p&gt;
&lt;p&gt;
So don't necessarily make assumptions about how your ORM is going to be generating
queries under the covers, especially if performance seems to be an issue when it shouldn't
be.
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
Some additional things to note:
&lt;/p&gt;
&lt;p&gt;
Castle ActiveRecord provides an ActiveRecordLinq.AsQueryable method that would appear
to be useable in place of the ISession.Linq method (with a call to new up a SessionScope
instead of calling CreateSession), but I couldn't get that to work (I didn't dig into
it).
&lt;/p&gt;
&lt;p&gt;
While the code sample above makes for a decent demo and a quick start, your mileage
will likely vary.&amp;nbsp; When things work great, they work great.&amp;nbsp; This sample
didn't end up being as I planned though because I had to work around / avoid things
that I couldn't easily get to work (like Order Details).&amp;nbsp; In the end, I am very
satisfied that the code sample is pretty short and straight-forward, yet so much power
is happening behind the scenes.
&lt;/p&gt;
&lt;p&gt;
NHibernate supports pretty much all the weirdness your database needs, but ActiveRecord
supports less weirdness, and ActiveWriter supports even less.&amp;nbsp; The higher up
the stack/abstraction you get, the more likely edge cases haven't been tested/implemented
yet.
&lt;/p&gt;
&lt;p&gt;
Now that you have the basic NHibernate Linq infrastructure in place, there are plenty
of Linq examples and sample code available elsewhere.
&lt;/p&gt;
&lt;p&gt;
Enjoy!
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.capprime.com/software_development_weblog/aggbug.ashx?id=162facaa-a3b9-4dc5-b770-657e27e887ad" /&gt;</description>
      <comments>http://www.capprime.com/software_development_weblog/CommentView,guid,162facaa-a3b9-4dc5-b770-657e27e887ad.aspx</comments>
      <category>.NET 3.5</category>
      <category>Knowledge Base</category>
      <category>LinqToSql</category>
      <category>NHibernate</category>
      <category>SQL Server</category>
      <category>Visual Studio 2008</category>
    </item>
    <item>
      <trackback:ping>http://www.capprime.com/software_development_weblog/Trackback.aspx?guid=a986b220-4052-430a-ab77-fab73a45a015</trackback:ping>
      <pingback:server>http://www.capprime.com/software_development_weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.capprime.com/software_development_weblog/PermaLink,guid,a986b220-4052-430a-ab77-fab73a45a015.aspx</pingback:target>
      <dc:creator>Michael Maddox</dc:creator>
      <wfw:comment>http://www.capprime.com/software_development_weblog/CommentView,guid,a986b220-4052-430a-ab77-fab73a45a015.aspx</wfw:comment>
      <wfw:commentRss>http://www.capprime.com/software_development_weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=a986b220-4052-430a-ab77-fab73a45a015</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
Disclaimer: I am not an ORM expert.  These tools have long learning curves and
very few people could effectively provide adequate unbiased guidance.  That said,
I am going to try to provide guidance based on the research I have done.  Your
mileage may vary.  This information is very time sensitive, these tools change
rapidly and this information will likely be significantly out of date by the end of
2009.  I have no vested interest in any of these projects.
</p>
        <p>
First off, what is ORM?  ORM stands for <a href="http://en.wikipedia.org/wiki/Object-relational_mapping">Object
Relational Mapping</a>.
</p>
        <p>
For any given project that updates data in a database:
</p>
        <p>
Should you use an ORM - Yes!<br />
Should you build your own custom ORM from scratch - No!<br />
Should you customize the ORM solution you choose - Probably
</p>
        <p>
These aren’t even really controversial opinions.  There was a time when ORMs
weren’t mature enough to be “safe”, but that time has passed.  The time saved
by using an ORM is a no brainer decision.
</p>
        <p>
There is even a pretty straight-forward answer to what .NET ORM you should be using:
</p>
        <p>
          <a href="https://www.hibernate.org/343.html">NHibernate</a>
        </p>
        <p>
The major advantages NHibernate has are:
</p>
        <ul>
          <li>
It's free (and open source)</li>
          <li>
It can handle enterprise class ORM problems</li>
          <li>
It has an active community surrounding it providing things it doesn't necessarily
have “out of the box” like code generation and "convention over configuration"</li>
          <li>
The majority of developer opinions regarding .NET ORM you will find on the Internet
mention NHibernate</li>
          <li>
It supports Linq (although not necessarily cleanly out of the box yet)</li>
        </ul>
        <p>
That isn’t to say that NHibernate doesn’t have disadvantages.  In particular,
the API can be difficult to work with.  In reality, I believe any ORM capable
of handling enterprise level ORM problems will have to expose a complex API and I
believe that justifies NHibernate’s complex API to some extent.  That said, there
are projects surrounding NHibernate to expose simpler interfaces into NHibernate (more
on a couple of those projects included below).
</p>
        <p>
In the end, unfortunately in my opinion, simplicity is not something you <strong><em>really</em></strong> want
in an ORM (I’m a simplicity nut, so this particular issue is very hard for me to cope
with personally).  The object relational impedance mismatch is a deceptively
complex problem.  Database performance is usually a very critical component of
any non-trivial application.  If you opt for a “simpler” ORM than NHibernate
today, you may regret that decision tomorrow by underestimating your needs for an
ORM.
</p>
        <p>
That said, if you aren’t an experienced programmer, or you just can’t make it over
the NHibernate learning curve, or you just don’t have enough time to work through
the NHibernate ramp up process right now, there is a good alternative worth recommending.
</p>
        <p>
          <a href="http://www.subsonicproject.com/">Subsonic</a> is a free, open source, "Microsoft
subsidized" ORM that aims for simplicity of the API and definitely delivers on that
front.  It can actually handle many of the common use cases that are required
of an ORM, but at some point you will fall off that “feature” cliff (for example:
having to deal with a poorly designed database that you cannot change).  You
can be productive with Subsonic very quickly and it is very powerful.
</p>
        <p>
Also, if you can’t use open source or would prefer a commercial product for whatever
reason, <a href="http://www.llblgen.com/">LLBLGen Pro</a> is worth recommending. 
It’s harder to find information about LLBLGen Pro since it’s not free, but it
appears to be a quality solution.  There is a fully functional 30 day demo available.
</p>
        <p>
Microsoft has entered the ORM market recently with two products: LinqToSql and EntityFramework. 
While Linq itself is a wonderful step forward for pretty much all .NET developers,
Microsoft’s ORM products are a major disappointment.  While Microsoft has promised
that EntityFramework will improve significantly with .NET 4.0, the evidence to back
that up so far is not compelling.  NHibernate seems to be way ahead of EntityFramework
and as I mentioned above, it’s pretty risky to gamble on a “partial ORM” solution.
</p>
        <p>
Thankfully, NHibernate and Subsonic support Linq, so you don't have to settle for
Microsoft’s ORM tools (although I’m sure many projects will be stuck using Microsoft’s
ORM, because it’s from Microsoft - I’ve been there personally and I’m sure I will
be there again).
</p>
        <p>
I mentioned above that you should probably customize/wrap your ORM of choice. 
Especially if you don’t choose NHibernate, I would work to isolate your ORM from the
rest of your code base so you can swap in NHibernate later if necessary.  While
it’s possible that there are unit test generators for ORMs out there, I haven’t seen
any and that seems like an obvious feature to have (generate basic unit tests for
your basic data and business level objects based on the models exposed by the ORM). 
I like to have auto generated unit tests for my data and business layers as a confidence
builder and as a base upon which to build more complex unit tests quickly.  There
are many other good reasons to wrap your ORM in a simpler, domain specific API.
</p>
        <p>
The biggest issue with integrating an ORM is to make sure you have very clear <a href="http://en.wikipedia.org/wiki/Separation_of_concerns">separation
of concerns</a>.  Your data layer should be the only layer with any exposure
to a connection string.  Your UI/Presentation Layer should not have any exposure
to your data layer.
</p>
        <p>
A very common temptation with ORMs is to use the “entity” objects they generate from
the database model as your “business layer”, when that is really your data layer and
you need to avoid mixing the two.  Please resist that temptation.  Unfortunately,
there is a truck load of sample code available on the Internet that blatantly violates
the separation of concerns concept.
</p>
        <p>
People new to NHibernate (and ORMs in general) should probably look into using one
of the following “helper” projects along with NHibernate to help with the ramp up.
</p>
        <p>
(1) <a href="http://fluentnhibernate.org/">Fluent NHibernate</a></p>
        <p>
This will help generate the XML mapping files between your objects and database so
you don’t have to write a bunch of XML by hand.
</p>
        <p>
(2) <a href="http://www.castleproject.org/activerecord/index.html">Castle ActiveRecord</a></p>
        <p>
I recommend this project, but have reservations at the same time.  The <a href="http://en.wikipedia.org/wiki/Active_record_pattern">Active
Record pattern</a> can really help beginners, especially people new to ORM, get their
head around how ORM works and why it’s beneficial.
</p>
        <p>
It can also trap you in a box that is difficult to get out of, so I would recommend
not getting too aggressive with the adoption of ActiveRecord until you have a good
feeling for its limitations.
</p>
        <p>
I would say start with ActiveRecord if you must, but get out of that box as soon as
you can and once you have enough experience with the alternatives, you can more safely
judge when ActiveRecord is the right answer.
</p>
        <p>
While there are many alternatives to ActiveRecord, one of the more common alternative
patterns is the <a href="http://martinfowler.com/eaaCatalog/unitOfWork.html">Unit
of Work</a> pattern.
</p>
        <p>
I share that just to provide additional information, you will probably not be able
to apply either pattern as documented without bumping into their limitations eventually.
</p>
        <p>
          <br />
I spent quite a bit of time reading about many other .NET ORMs before posting this
article, but for various reasons they weren’t included in the article.  Some
of the primary reasons for non-inclusion were:
</p>
        <p>
(1) Lack of Linq support or lack of stated intent to provide Linq support<br />
(2) Lack of recommendations from real developers while doing various Google searches
</p>
        <p>
These seem like two pretty easy to apply criteria to separate “good” ORM from “bad”
ORM (and there are a lot of bad ORMs - and I would hope most people try to code their
own simple ORM sometime to help them understand how easy it is to create a bad ORM).
</p>
        <p>
I would like to thank the following four bloggers specifically:
</p>
        <p>
          <a href="http://ayende.com/Blog/">Ayende Rahien/Oren Eini</a>, <a href="http://blog.wekeroad.com/">Rob
Conery</a>, <a href="http://weblogs.asp.net/FBouma/">Frans Bouma</a>, and <a href="http://www.davidhayden.com/blog/dave/">David
Hayden</a></p>
        <p>
for their extensive writing on .NET ORM who helped frame much of what I have recommended
in this article.  Blogging about your ORM helps give confidence to those who
want to use or recommend your ORM, so you will see a correlation between these bloggers
and the tools I recommended.
</p>
        <p>
 
</p>
        <img width="0" height="0" src="http://www.capprime.com/software_development_weblog/aggbug.ashx?id=a986b220-4052-430a-ab77-fab73a45a015" />
      </body>
      <title>.NET and ORM - Decisions, decisions</title>
      <guid isPermaLink="false">http://www.capprime.com/software_development_weblog/PermaLink,guid,a986b220-4052-430a-ab77-fab73a45a015.aspx</guid>
      <link>http://www.capprime.com/software_development_weblog/2009/07/18/NETAndORMDecisionsDecisions.aspx</link>
      <pubDate>Sat, 18 Jul 2009 12:48:28 GMT</pubDate>
      <description>&lt;p&gt;
Disclaimer: I am not an ORM expert.&amp;nbsp; These tools have long learning curves and
very few people could effectively provide adequate unbiased guidance.&amp;nbsp; That said,
I am going to try to provide guidance based on the research I have done.&amp;nbsp; Your
mileage may vary.&amp;nbsp; This information is very time sensitive, these tools change
rapidly and this information will likely be significantly out of date by the end of
2009.&amp;nbsp; I have no vested interest in any of these projects.
&lt;/p&gt;
&lt;p&gt;
First off, what is ORM?&amp;nbsp; ORM stands for &lt;a href="http://en.wikipedia.org/wiki/Object-relational_mapping"&gt;Object
Relational Mapping&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
For any given project that updates data in a database:
&lt;/p&gt;
&lt;p&gt;
Should you use an ORM - Yes!&lt;br&gt;
Should you build your own custom ORM from scratch - No!&lt;br&gt;
Should you customize the ORM solution you choose - Probably
&lt;/p&gt;
&lt;p&gt;
These aren’t even really controversial opinions.&amp;nbsp; There was a time when ORMs
weren’t mature enough to be “safe”, but that time has passed.&amp;nbsp; The time saved
by using an ORM is a no brainer decision.
&lt;/p&gt;
&lt;p&gt;
There is even a pretty straight-forward answer to what .NET ORM you should be using:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="https://www.hibernate.org/343.html"&gt;NHibernate&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
The major advantages NHibernate has are:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
It's free (and open source)&lt;/li&gt;
&lt;li&gt;
It can handle enterprise class ORM problems&lt;/li&gt;
&lt;li&gt;
It has an active community surrounding it providing things it doesn't necessarily
have “out of the box” like code generation and "convention over configuration"&lt;/li&gt;
&lt;li&gt;
The majority of developer opinions regarding .NET ORM you will find on the Internet
mention NHibernate&lt;/li&gt;
&lt;li&gt;
It supports Linq (although not necessarily cleanly out of the box yet)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
That isn’t to say that NHibernate doesn’t have disadvantages.&amp;nbsp; In particular,
the API can be difficult to work with.&amp;nbsp; In reality, I believe any ORM capable
of handling enterprise level ORM problems will have to expose a complex API and I
believe that justifies NHibernate’s complex API to some extent.&amp;nbsp; That said, there
are projects surrounding NHibernate to expose simpler interfaces into NHibernate (more
on a couple of those projects included below).
&lt;/p&gt;
&lt;p&gt;
In the end, unfortunately in my opinion, simplicity is not something you &lt;strong&gt;&lt;em&gt;really&lt;/em&gt;&lt;/strong&gt; want
in an ORM (I’m a simplicity nut, so this particular issue is very hard for me to cope
with personally).&amp;nbsp; The object relational impedance mismatch is a deceptively
complex problem.&amp;nbsp; Database performance is usually a very critical component of
any non-trivial application.&amp;nbsp; If you opt for a “simpler” ORM than NHibernate
today, you may regret that decision tomorrow by underestimating your needs for an
ORM.
&lt;/p&gt;
&lt;p&gt;
That said, if you aren’t an experienced programmer, or you just can’t make it over
the NHibernate learning curve, or you just don’t have enough time to work through
the NHibernate ramp up process right now, there is a good alternative worth recommending.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.subsonicproject.com/"&gt;Subsonic&lt;/a&gt; is a free, open source, "Microsoft
subsidized" ORM that aims for simplicity of the API and definitely delivers on that
front.&amp;nbsp; It can actually handle many of the common use cases that are required
of an ORM, but at some point you will fall off that “feature” cliff (for example:
having to deal with a poorly designed database that you cannot change).&amp;nbsp; You
can be productive with Subsonic very quickly and it is very powerful.
&lt;/p&gt;
&lt;p&gt;
Also, if you can’t use open source or would prefer a commercial product for whatever
reason, &lt;a href="http://www.llblgen.com/"&gt;LLBLGen Pro&lt;/a&gt; is worth recommending.&amp;nbsp;
It’s harder to find information about LLBLGen Pro&amp;nbsp;since it’s not free, but it
appears to be a quality solution.&amp;nbsp; There is a fully functional 30 day demo available.
&lt;/p&gt;
&lt;p&gt;
Microsoft has entered the ORM market recently with two products: LinqToSql and EntityFramework.&amp;nbsp;
While Linq itself is a wonderful step forward for pretty much all .NET developers,
Microsoft’s ORM products are a major disappointment.&amp;nbsp; While Microsoft has promised
that EntityFramework will improve significantly with .NET 4.0, the evidence to back
that up so far is not compelling.&amp;nbsp; NHibernate seems to be way ahead of EntityFramework
and as I mentioned above, it’s pretty risky to gamble on a “partial ORM” solution.
&lt;/p&gt;
&lt;p&gt;
Thankfully, NHibernate and Subsonic support Linq, so you don't have to settle for
Microsoft’s ORM tools (although I’m sure many projects will be stuck using Microsoft’s
ORM, because it’s from Microsoft - I’ve been there personally and I’m sure I will
be there again).
&lt;/p&gt;
&lt;p&gt;
I mentioned above that you should probably customize/wrap your ORM of choice.&amp;nbsp;
Especially if you don’t choose NHibernate, I would work to isolate your ORM from the
rest of your code base so you can swap in NHibernate later if necessary.&amp;nbsp; While
it’s possible that there are unit test generators for ORMs out there, I haven’t seen
any and that seems like an obvious feature to have (generate basic unit tests for
your basic data and business level objects based on the models exposed by the ORM).&amp;nbsp;
I like to have auto generated unit tests for my data and business layers as a confidence
builder and as a base upon which to build more complex unit tests quickly.&amp;nbsp; There
are many other good reasons to wrap your ORM in a simpler, domain specific API.
&lt;/p&gt;
&lt;p&gt;
The biggest issue with integrating an ORM is to make sure you have very clear &lt;a href="http://en.wikipedia.org/wiki/Separation_of_concerns"&gt;separation
of concerns&lt;/a&gt;.&amp;nbsp; Your data layer should be the only layer with any exposure
to a connection string.&amp;nbsp; Your UI/Presentation Layer should not have any exposure
to your data layer.
&lt;/p&gt;
&lt;p&gt;
A very common temptation with ORMs is to use the “entity” objects they generate from
the database model as your “business layer”, when that is really your data layer and
you need to avoid mixing the two.&amp;nbsp; Please resist that temptation.&amp;nbsp; Unfortunately,
there is a truck load of sample code available on the Internet that blatantly violates
the separation of concerns concept.
&lt;/p&gt;
&lt;p&gt;
People new to NHibernate (and ORMs in general) should probably look into using one
of the following “helper” projects along with NHibernate to help with the ramp up.
&lt;/p&gt;
&lt;p&gt;
(1) &lt;a href="http://fluentnhibernate.org/"&gt;Fluent NHibernate&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
This will help generate the XML mapping files between your objects and database so
you don’t have to write a bunch of XML by hand.
&lt;/p&gt;
&lt;p&gt;
(2) &lt;a href="http://www.castleproject.org/activerecord/index.html"&gt;Castle ActiveRecord&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
I recommend this project, but have reservations at the same time.&amp;nbsp; The &lt;a href="http://en.wikipedia.org/wiki/Active_record_pattern"&gt;Active
Record pattern&lt;/a&gt; can really help beginners, especially people new to ORM, get their
head around how ORM works and why it’s beneficial.
&lt;/p&gt;
&lt;p&gt;
It can also trap you in a box that is difficult to get out of, so I would recommend
not getting too aggressive with the adoption of ActiveRecord until you have a good
feeling for its limitations.
&lt;/p&gt;
&lt;p&gt;
I would say start with ActiveRecord if you must, but get out of that box as soon as
you can and once you have enough experience with the alternatives, you can more safely
judge when ActiveRecord is the right answer.
&lt;/p&gt;
&lt;p&gt;
While there are many alternatives to ActiveRecord, one of the more common alternative
patterns is the &lt;a href="http://martinfowler.com/eaaCatalog/unitOfWork.html"&gt;Unit
of Work&lt;/a&gt; pattern.
&lt;/p&gt;
&lt;p&gt;
I share that just to provide additional information, you will probably not be able
to apply either pattern as documented without bumping into their limitations eventually.
&lt;/p&gt;
&lt;p&gt;
&lt;br&gt;
I spent quite a bit of time reading about many other .NET ORMs before posting this
article, but for various reasons they weren’t included in the article.&amp;nbsp; Some
of the primary reasons for non-inclusion were:
&lt;/p&gt;
&lt;p&gt;
(1) Lack of Linq support or lack of stated intent to provide Linq support&lt;br&gt;
(2) Lack of recommendations from real developers while doing various Google searches
&lt;/p&gt;
&lt;p&gt;
These seem like two pretty easy to apply criteria to separate “good” ORM from “bad”
ORM (and there are a lot of bad ORMs - and I would hope most people try to code their
own simple ORM sometime to help them understand how easy it is to create a bad ORM).
&lt;/p&gt;
&lt;p&gt;
I would like to thank the following four bloggers specifically:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://ayende.com/Blog/"&gt;Ayende Rahien/Oren Eini&lt;/a&gt;, &lt;a href="http://blog.wekeroad.com/"&gt;Rob
Conery&lt;/a&gt;, &lt;a href="http://weblogs.asp.net/FBouma/"&gt;Frans Bouma&lt;/a&gt;, and &lt;a href="http://www.davidhayden.com/blog/dave/"&gt;David
Hayden&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
for their extensive writing on .NET ORM who helped frame much of what I have recommended
in this article.&amp;nbsp; Blogging about your ORM helps give confidence to those who
want to use or recommend your ORM, so you will see a correlation between these bloggers
and the tools I recommended.
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.capprime.com/software_development_weblog/aggbug.ashx?id=a986b220-4052-430a-ab77-fab73a45a015" /&gt;</description>
      <comments>http://www.capprime.com/software_development_weblog/CommentView,guid,a986b220-4052-430a-ab77-fab73a45a015.aspx</comments>
      <category>Knowledge Base</category>
      <category>LinqToSql</category>
      <category>SQL Server</category>
      <category>NHibernate</category>
    </item>
    <item>
      <trackback:ping>http://www.capprime.com/software_development_weblog/Trackback.aspx?guid=f1a9b52c-b407-4cbb-9197-4bae289ae11d</trackback:ping>
      <pingback:server>http://www.capprime.com/software_development_weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.capprime.com/software_development_weblog/PermaLink,guid,f1a9b52c-b407-4cbb-9197-4bae289ae11d.aspx</pingback:target>
      <dc:creator>Michael Maddox</dc:creator>
      <wfw:comment>http://www.capprime.com/software_development_weblog/CommentView,guid,f1a9b52c-b407-4cbb-9197-4bae289ae11d.aspx</wfw:comment>
      <wfw:commentRss>http://www.capprime.com/software_development_weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=f1a9b52c-b407-4cbb-9197-4bae289ae11d</wfw:commentRss>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
          <strong>There are a number of very significant drawbacks in the O/R Designer that
have no reasonable work around.</strong>
        </p>
        <ul>
          <li>
The Visual Studio 2008 LinqToSql O/R Designer is fine for a database with ~5 tables,
no views, no stored procedures, and no functions, but it doesn't scale well much beyond
that. 
<ul><li>
If the database changes, it's very difficult to manually update the O/R Designer properly. 
As database complexity increases, this becomes near impossible. 
</li><li>
When you need to remove an existing object from the O/R Designer to force it to update,
it can be difficult to find that object.</li></ul></li>
          <li>
It is overly difficult to diff the generated files from one version to another since
the files are rewritten in a different order than they were read in when changes are
made.  Even if the files can be sorted in a reasonable way, diffing the files
is still not an effective solution for managing changes. 
</li>
          <li>
There are bugs with how the O/R Designer generates code.  In general, it is difficult
to evaluate if the O/R Designer is working properly since it is difficult to diff
the generated files before and after generation.  There are cases where the O/R
Designer output is different than the SQL Metal output and in some of those cases,
it could be a bug in either or both of the tools. 
</li>
          <li>
If two or more developers are working under an edit/merge/commit style of source control,
it is difficult to resolve conflicts in the LinqToSql O/R Designer files during the
merge phase. 
</li>
          <li>
It is not effective to try to diff O/R Designer generated files against files generated
by SQL Metal as they don't use the same underlying code generation techniques and
file sorting.  The two tools also have meaningfully different feature sets which
negatively impacts the ability to diff the underlying files.</li>
        </ul>
        <p>
Once you start down the path of the O/R Designer, it gets increasingly harder to migrate
away from it the farther you go.  This is a significant hidden risk as many of
the scalability issues with the tool don’t present themselves right away.
</p>
        <p>
It's not clear if any of these problems will be addressed in Visual Studio 2010.
</p>
        <p>
This is not to say that the O/R Designer doesn't have very interesting and useful
features.  It does have interesting and useful features.  They just aren't
packaged in a way to make them at all usable for anything but very tiny databases.
</p>
        <p>
          <strong>Are there alternative LinqToSql code generation tools?</strong>
        </p>
        <p>
The main alternative tool is SQL Metal, which has quite a few drawbacks of its own. 
While SQL Metal can scale up to much larger databases than the O/R Designer, it still
can't scale effectively past a certain point.
</p>
        <p>
Another free alternative is <a href="http://l2st4.codeplex.com/">Damien Guard's LinqToSQL
T4 Template</a>.  Since the T4 template is not an official product of Microsoft
and was built by a developer in their spare time, you'll have to judge for yourself
whether it meets your criteria for "production worthy".
</p>
        <p>
I may write a future blog entry with additional details on SQL Metal and the T4 templates.
</p>
        <p>
There are non-free alternatives to the O/R Designer as well, but in many cases it
is just not possible to get software tool purchases approved as part of the software
development project budget.  It would be surprising if LinqToSql adoption hinged
on the success of commercial third party tools.
</p>
        <p>
Updated 2009/09/16 - Related blog posts:
</p>
        <p>
          <a href="http://www.capprime.com/software_development_weblog/PermaLink,guid,78e9dd46-b743-4d10-a541-2593354028ba.aspx">The
drawbacks of adopting Linq To Sql</a>
          <br />
          <a href="http://www.capprime.com/software_development_weblog/PermaLink,guid,a986b220-4052-430a-ab77-fab73a45a015.aspx">.NET
and ORM - Decisions, decisions</a>
        </p>
        <img width="0" height="0" src="http://www.capprime.com/software_development_weblog/aggbug.ashx?id=f1a9b52c-b407-4cbb-9197-4bae289ae11d" />
      </body>
      <title>Do not use the Visual Studio 2008 LinqToSql O/R Designer</title>
      <guid isPermaLink="false">http://www.capprime.com/software_development_weblog/PermaLink,guid,f1a9b52c-b407-4cbb-9197-4bae289ae11d.aspx</guid>
      <link>http://www.capprime.com/software_development_weblog/2009/06/06/DoNotUseTheVisualStudio2008LinqToSqlORDesigner.aspx</link>
      <pubDate>Sat, 06 Jun 2009 09:02:30 GMT</pubDate>
      <description>&lt;p&gt;
&lt;strong&gt;There are a number of very significant drawbacks in the O/R Designer that
have no reasonable work around.&lt;/strong&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
The Visual Studio 2008 LinqToSql O/R Designer is fine for a database with ~5 tables,
no views, no stored procedures, and no functions, but it doesn't scale well much beyond
that. 
&lt;ul&gt;
&lt;li&gt;
If the database changes, it's very difficult to manually update the O/R Designer properly.&amp;nbsp;
As database complexity increases, this becomes near impossible. 
&lt;li&gt;
When you need to remove an existing object from the O/R Designer to force it to update,
it can be difficult to find that object.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;
It is overly difficult to diff the generated files from one version to another since
the files are rewritten in a different order than they were read in when changes are
made.&amp;nbsp; Even if the files can be sorted in a reasonable way, diffing the files
is still not an effective solution for managing changes. 
&lt;li&gt;
There are bugs with how the O/R Designer generates code.&amp;nbsp; In general, it is difficult
to evaluate if the O/R Designer is working properly since it is difficult to diff
the generated files before and after generation.&amp;nbsp; There are cases where the O/R
Designer output is different than the SQL Metal output and in some of those cases,
it could be a bug in either or both of the tools. 
&lt;li&gt;
If two or more developers are working under an edit/merge/commit style of source control,
it is difficult to resolve conflicts in the LinqToSql O/R Designer files during the
merge phase. 
&lt;li&gt;
It is not effective to try to diff O/R Designer generated files against files generated
by SQL Metal as they don't use the same underlying code generation techniques and
file sorting.&amp;nbsp; The two tools also have meaningfully different feature sets which
negatively impacts the ability to diff the underlying files.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Once you start down the path of the O/R Designer, it gets increasingly harder to migrate
away from it the farther you go.&amp;nbsp; This is a significant hidden risk as many of
the scalability issues with the tool don’t present themselves right away.
&lt;/p&gt;
&lt;p&gt;
It's not clear if any of these problems will be addressed in Visual Studio 2010.
&lt;/p&gt;
&lt;p&gt;
This is not to say that the O/R Designer doesn't have very interesting and useful
features.&amp;nbsp; It does have interesting and useful features.&amp;nbsp; They just aren't
packaged in a way to make them at all usable for anything but very tiny databases.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;Are there alternative LinqToSql code generation tools?&lt;/strong&gt;
&lt;/p&gt;
&lt;p&gt;
The main alternative tool is SQL Metal, which has quite a few drawbacks of its own.&amp;nbsp;
While SQL Metal can scale up to much larger databases than the O/R Designer, it still
can't scale effectively past a certain point.
&lt;/p&gt;
&lt;p&gt;
Another free alternative is &lt;a href="http://l2st4.codeplex.com/"&gt;Damien Guard's LinqToSQL
T4 Template&lt;/a&gt;.&amp;nbsp; Since the T4 template is not an official product of Microsoft
and was built by a developer in their spare time, you'll have to judge for yourself
whether it meets your criteria for "production worthy".
&lt;/p&gt;
&lt;p&gt;
I may write a future blog entry with additional details on SQL Metal and the T4 templates.
&lt;/p&gt;
&lt;p&gt;
There are non-free alternatives to the O/R Designer as well, but in many cases it
is just not possible to get software tool purchases approved as part of the software
development project budget.&amp;nbsp; It would be surprising if LinqToSql adoption hinged
on the success of commercial third party tools.
&lt;/p&gt;
&lt;p&gt;
Updated 2009/09/16 -&amp;nbsp;Related blog posts:
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.capprime.com/software_development_weblog/PermaLink,guid,78e9dd46-b743-4d10-a541-2593354028ba.aspx"&gt;The
drawbacks of adopting Linq To Sql&lt;/a&gt;
&lt;br&gt;
&lt;a href="http://www.capprime.com/software_development_weblog/PermaLink,guid,a986b220-4052-430a-ab77-fab73a45a015.aspx"&gt;.NET
and ORM - Decisions, decisions&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.capprime.com/software_development_weblog/aggbug.ashx?id=f1a9b52c-b407-4cbb-9197-4bae289ae11d" /&gt;</description>
      <comments>http://www.capprime.com/software_development_weblog/CommentView,guid,f1a9b52c-b407-4cbb-9197-4bae289ae11d.aspx</comments>
      <category>LinqToSql</category>
      <category>Tools</category>
      <category>Visual Studio 2008</category>
    </item>
    <item>
      <trackback:ping>http://www.capprime.com/software_development_weblog/Trackback.aspx?guid=78e9dd46-b743-4d10-a541-2593354028ba</trackback:ping>
      <pingback:server>http://www.capprime.com/software_development_weblog/pingback.aspx</pingback:server>
      <pingback:target>http://www.capprime.com/software_development_weblog/PermaLink,guid,78e9dd46-b743-4d10-a541-2593354028ba.aspx</pingback:target>
      <dc:creator>Michael Maddox</dc:creator>
      <wfw:comment>http://www.capprime.com/software_development_weblog/CommentView,guid,78e9dd46-b743-4d10-a541-2593354028ba.aspx</wfw:comment>
      <wfw:commentRss>http://www.capprime.com/software_development_weblog/SyndicationService.asmx/GetEntryCommentsRss?guid=78e9dd46-b743-4d10-a541-2593354028ba</wfw:commentRss>
      <slash:comments>3</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
LinqToSql does offer benefits to corporate IT organizations.  Microsoft marketing
has helped spread that message.
</p>
        <p>
It's less clear what the drawbacks of Linq To Sql are, yet I believe the drawbacks
are important to consider before adopting such a large disruptive change into a software
development environment.
</p>
        <p>
Here are some of the downsides to LinqToSql that I have identified so far:
</p>
        <ul>
          <li>
There is a significant learning curve.  The technology is deceptively approachable. 
On the surface, for instance, LinqToSql takes a SQL Server database table and generates
.NET source code for a .NET CLR class.  This appears to be a nice abstraction. 
However, there is a significant amount of complexity involved.  The abstraction <a href="http://en.wikipedia.org/wiki/Leaky_abstraction">leaks</a>. 
Something doesn't work as you expect, so you start searching and reading and the reading
seems to go on a lot longer than expected.  We are still early enough in the
adoption cycle that many common issues and questions are under documented. 
</li>
          <li>
There is immature documentation.  As technologies mature, the documentation improves. 
This is especially true of the documentation of more obscure issues available through
things like google searches.  Right now, there are "<a href="http://en.wikipedia.org/wiki/Gotcha_(programming)">gotchas</a>"
that remain hard to find clear discussion around. 
</li>
          <li>
There is a requirement for "seasoned" developers on the team.  The development
team needs one or more developers who can learn new things quickly, handle significant
amounts of complexity, and do the right thing without micromanagement.  These
developers likely need significant SQL Server, ADO.NET, and object relational mapping expertise. 
There is a limited quantity of these seasoned developers to go around. 
</li>
          <li>
There is significant competition.  There are a lot of players in the object relational
mapping (ORM) world.  LinqToSql, other than being included free in Visual Studio,
arguably doesn't add enough value (yet) to the space.  Many of the highest
traffic parts of LinqToSql can be (and have been extensively) emulated with ADO.NET. 
</li>
          <li>
There is a significant amount of <a href="http://en.wikipedia.org/wiki/Fear,_uncertainty_and_doubt">FUD</a> and
confusion around the future roadmap (i.e. version 2 and beyond) for Linq To Sql. 
Microsoft is actively de-emphasizing Linq To Sql while maintaining that they will
continue to support it for the foreseeable future.  While the Entity Framework
may some day be a clear and straight-forward migration path for current Linq To Sql
users, that is not the case today and Microsoft is having trouble with damage control
around their confusing and mixed messages.  I wish I could link to something
worth reading on this topic, but as I've said, Microsoft has really botched the communication
on this issue. 
</li>
          <li>
There are significant bugs.  That is a normal course of business with anything
that is basically on version 1 (and since VS 2008 SP1 has been released, LinqToSql
could possibly be called version 2).  Here's an <a href="http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=455456">example</a> of
a bug that is likely to hit a decent portion of the LinqToSql user base. 
</li>
          <li>
There are significant tooling issues.  The O/R Designer and SQLMetal tools that
come with VS 2008 are fairly blunt objects with fairly significant limitations. 
While some commercial products have stepped in to fill some of the gaps, there are
very limited free options available.  I hope to write a future blog entry with
more details on the limitations in the VS 2008 LinqToSql tools (for one, see <a href="http://www.capprime.com/software_development_weblog/PermaLink,guid,f1a9b52c-b407-4cbb-9197-4bae289ae11d.aspx">Do
not use the Visual Studio 2008 LinqToSql O/R Designer</a>).</li>
        </ul>
        <p>
LinqToSql will appeal to many people for many reasons and I think its momentum is
likely unstoppable.
</p>
        <p>
As with adopting any new technology, it's important to go in with your eyes open.  
</p>
        <p>
Your mileage may vary.
</p>
        <p>
Update 2009/09/16 - Here is a somewhat related follow-up blog post discussing where
Linq2Sql matches up against other .NET ORMs: <a href="http://www.capprime.com/software_development_weblog/PermaLink,guid,a986b220-4052-430a-ab77-fab73a45a015.aspx">.NET
and ORM - Decisions, decisions</a></p>
        <img width="0" height="0" src="http://www.capprime.com/software_development_weblog/aggbug.ashx?id=78e9dd46-b743-4d10-a541-2593354028ba" />
      </body>
      <title>The drawbacks of adopting Linq To Sql</title>
      <guid isPermaLink="false">http://www.capprime.com/software_development_weblog/PermaLink,guid,78e9dd46-b743-4d10-a541-2593354028ba.aspx</guid>
      <link>http://www.capprime.com/software_development_weblog/2009/05/29/TheDrawbacksOfAdoptingLinqToSql.aspx</link>
      <pubDate>Fri, 29 May 2009 11:22:38 GMT</pubDate>
      <description>&lt;p&gt;
LinqToSql does offer benefits to corporate IT organizations.&amp;nbsp; Microsoft marketing
has helped spread that message.
&lt;/p&gt;
&lt;p&gt;
It's less clear what the drawbacks of Linq To Sql are, yet I believe the drawbacks
are important to consider before adopting such a large disruptive change into a software
development environment.
&lt;/p&gt;
&lt;p&gt;
Here are some of the downsides to LinqToSql that I have identified so far:
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
There is a significant learning curve.&amp;nbsp; The technology is deceptively approachable.&amp;nbsp;
On the surface, for instance, LinqToSql takes a SQL Server database table and generates
.NET source code for a .NET CLR class.&amp;nbsp; This appears to be a nice abstraction.&amp;nbsp;
However, there is a significant amount of complexity involved.&amp;nbsp; The abstraction &lt;a href="http://en.wikipedia.org/wiki/Leaky_abstraction"&gt;leaks&lt;/a&gt;.&amp;nbsp;
Something doesn't work as you expect, so you start searching and reading and the reading
seems to go on a lot longer than expected.&amp;nbsp; We are still early enough in the
adoption cycle that many common issues and questions are under documented. 
&lt;li&gt;
There is immature documentation.&amp;nbsp; As technologies mature, the documentation&amp;nbsp;improves.&amp;nbsp;
This is especially true of the documentation of more obscure issues available through
things like google searches.&amp;nbsp; Right now, there are "&lt;a href="http://en.wikipedia.org/wiki/Gotcha_(programming)"&gt;gotchas&lt;/a&gt;"
that remain hard to find clear discussion around. 
&lt;li&gt;
There is a requirement for "seasoned" developers on the team.&amp;nbsp; The development
team needs one or more developers who can learn new things quickly, handle significant
amounts of complexity, and do the right thing without micromanagement.&amp;nbsp; These
developers likely need significant SQL Server, ADO.NET, and object relational mapping&amp;nbsp;expertise.&amp;nbsp;
There is a limited quantity of these seasoned developers to go around. 
&lt;li&gt;
There is significant competition.&amp;nbsp; There are a lot of players in the object relational
mapping (ORM) world.&amp;nbsp; LinqToSql, other than being included free in Visual Studio,
arguably doesn't add enough value (yet)&amp;nbsp;to the space.&amp;nbsp; Many of the highest
traffic parts of LinqToSql can be (and have been extensively) emulated with ADO.NET. 
&lt;li&gt;
There is a significant amount of &lt;a href="http://en.wikipedia.org/wiki/Fear,_uncertainty_and_doubt"&gt;FUD&lt;/a&gt; and
confusion around the future roadmap (i.e. version 2 and beyond) for Linq To Sql.&amp;nbsp;
Microsoft is actively de-emphasizing Linq To Sql while maintaining that they will
continue to support it for the foreseeable future.&amp;nbsp; While the Entity Framework
may some day be a clear and straight-forward migration path for current Linq To Sql
users, that is not the case today and Microsoft is having trouble with damage control
around their confusing and mixed messages.&amp;nbsp; I wish I could link to something
worth reading on this topic, but as I've said, Microsoft has really botched the communication
on this issue. 
&lt;li&gt;
There are significant bugs.&amp;nbsp; That is a normal course of business with anything
that is basically on version 1 (and since VS 2008 SP1 has been released, LinqToSql
could possibly be called version 2).&amp;nbsp; Here's an &lt;a href="http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=455456"&gt;example&lt;/a&gt;&amp;nbsp;of
a bug that is likely to hit a decent portion of the LinqToSql user base. 
&lt;li&gt;
There are significant tooling issues.&amp;nbsp; The O/R Designer and SQLMetal tools that
come with VS 2008 are fairly blunt objects with fairly significant limitations.&amp;nbsp;
While some commercial products have stepped in to fill some of the gaps, there are
very limited free options available.&amp;nbsp; I hope to write a future blog entry with
more details on the limitations in the VS 2008 LinqToSql tools (for one, see &lt;a href="http://www.capprime.com/software_development_weblog/PermaLink,guid,f1a9b52c-b407-4cbb-9197-4bae289ae11d.aspx"&gt;Do
not use the Visual Studio 2008 LinqToSql O/R Designer&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
LinqToSql will appeal to many people for many reasons and I think its momentum is
likely unstoppable.
&lt;/p&gt;
&lt;p&gt;
As with adopting any new technology, it's important to go in with your eyes open.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
Your mileage may vary.
&lt;/p&gt;
&lt;p&gt;
Update 2009/09/16 - Here is a somewhat related follow-up blog post discussing where
Linq2Sql matches up against other .NET ORMs: &lt;a href="http://www.capprime.com/software_development_weblog/PermaLink,guid,a986b220-4052-430a-ab77-fab73a45a015.aspx"&gt;.NET
and ORM - Decisions, decisions&lt;/a&gt;
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.capprime.com/software_development_weblog/aggbug.ashx?id=78e9dd46-b743-4d10-a541-2593354028ba" /&gt;</description>
      <comments>http://www.capprime.com/software_development_weblog/CommentView,guid,78e9dd46-b743-4d10-a541-2593354028ba.aspx</comments>
      <category>LinqToSql</category>
      <category>Visual Studio 2008</category>
    </item>
  </channel>
</rss>