<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" 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/" version="2.0">
  <channel>
    <title>AboutCode.net - data_access</title>
    <link>http://www.aboutcode.net/</link>
    <description>Thoughts on Software by Andrew Davey</description>
    <language>en-us</language>
    <copyright>Andrew Davey</copyright>
    <lastBuildDate>Mon, 27 Aug 2007 09:41:09 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.2.8279.16125</generator>
    <managingEditor>andrew@equin.co.uk</managingEditor>
    <webMaster>andrew@equin.co.uk</webMaster>
    <item>
      <trackback:ping>http://www.aboutcode.net/Trackback.aspx?guid=d9660556-29e4-4b45-b420-d42ef678d63e</trackback:ping>
      <pingback:server>http://www.aboutcode.net/pingback.aspx</pingback:server>
      <pingback:target>http://www.aboutcode.net/PermaLink,guid,d9660556-29e4-4b45-b420-d42ef678d63e.aspx</pingback:target>
      <dc:creator />
      <wfw:comment>http://www.aboutcode.net/CommentView,guid,d9660556-29e4-4b45-b420-d42ef678d63e.aspx</wfw:comment>
      <wfw:commentRss>http://www.aboutcode.net/SyndicationService.asmx/GetEntryCommentsRss?guid=d9660556-29e4-4b45-b420-d42ef678d63e</wfw:commentRss>
      <slash:comments>1</slash:comments>
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
I have so far managed to avoid needing to use any fancy ORM tools. However, this doesn't
mean I like writing all the standard ADO.NET code by hand. Using C# 2.0 anonymous
methods I am able to write code like the following. (I'm not sure all of this is truly
original work; if you have already done this then sweet! I just want to share
the ideas with everyone.)
</p>
        <p>
Customer c = With.Database&lt;Customer&gt;(delegate(Database db)<br />
{<br />
    return db.ExecuteReader&lt;Customer&gt;(<br />
        "select Id, FirstName, Surname from Customer
where Id = @id", // The SQL to execute<br />
        delegate(IDbCommand cmd) // This anonymous
function is called before executing so we can add params.<br />
        {<br />
            db.AddParameter(cmd,
"@id", DbType.Int32, id);<br />
        },<br />
        delegate(IDataReader reader) // The
IDataReader returned from ExecuteReader is passed here.<br />
        {<br />
            if (reader.Read())<br />
               
return new Customer(<br />
                   
reader.GetInt32(0),<br />
                   
reader.GetString(1),<br />
                   
reader.GetString(2));<br />
            else<br />
               
return null;<br />
        });<br />
}); 
</p>
        <p>
My Database class manages the creation of a connection and optionally a transaction.
It then exposes methods to invoke SQL commands (Reader, Scalar and NonQuery). A transaction
can be automatically provided by calling With.DatabaseInTransaction( ... ) instead.
This then wraps the inputted action in a try-catch-finally block, commit and rolling
back in the usual places.
</p>
        <p>
("With" is a static class that provides convenient access to the Database object) 
</p>
        <p>
public static T DatabaseInTransaction&lt;T&gt;(Function&lt;Database, T&gt; function)<br />
{<br />
    using (Database db = new Database())<br />
    {<br />
        db.BeginTransaction();<br />
        try<br />
        {<br />
            T result = function(db);<br />
            db.CommitTransaction();<br />
            return result;<br />
        }<br />
        catch<br />
        {<br />
            db.RollbackTransaction();<br />
            throw;<br />
        }<br />
    }<br />
} 
</p>
        <p>
There are generic and non-generic versions of the functions, depending on if we want
to return a value. 
</p>
        <p>
For example, here is the non-generic ExecuteReader method from Database: 
</p>
        <p>
public void ExecuteReader(string sql, Action&lt;IDbCommand&gt; addParameters, Action&lt;IDataReader&gt;
action)<br />
{<br />
    Debug.Assert(sql != null, "sql cannot be null.");<br />
    Debug.Assert(action != null, "action cannot be null."); 
</p>
        <p>
    using (IDbCommand cmd = CreateCommand(sql))<br />
    {<br />
        if (addParameters != null)<br />
        {<br />
            addParameters(cmd);<br />
        }<br />
        using (IDataReader reader = cmd.ExecuteReader())<br />
        {<br />
            action(reader);<br />
        }<br />
    }<br />
} 
</p>
        <p>
The IDbCommand is created using the following method. Notice that we also handle assigning
the transaction if we're in one.
</p>
        <p>
IDbCommand CreateCommand(string sql)<br />
{<br />
    Debug.Assert(_connection != null &amp;&amp; _connection.State ==
ConnectionState.Open); 
</p>
        <p>
    IDbCommand cmd = _connection.CreateCommand();<br />
    cmd.CommandText = sql;<br />
    cmd.CommandType = CommandType.Text;<br />
    if (_transaction != null)<br />
    {<br />
        cmd.Transaction = _transaction;<br />
    }<br />
    return cmd;<br />
} 
</p>
        <p>
The Database class implements IDisposable, thus allowing the "using" syntax in the
With class methods. In Dispose() I close the connection, if the transaction is still
open I rollback first.
</p>
        <p>
I anyone wants the full Database and With classes drop me a line. I'm looking forward
to C# 3.0 since the improved type inference and lambda syntax will slim down the amount
of keyboard time even more!
</p>
        <img width="0" height="0" src="http://www.aboutcode.net/aggbug.ashx?id=d9660556-29e4-4b45-b420-d42ef678d63e" />
      </body>
      <title>Data Access Syntax Using Anonymous Methods</title>
      <guid isPermaLink="false">http://www.aboutcode.net/PermaLink,guid,d9660556-29e4-4b45-b420-d42ef678d63e.aspx</guid>
      <link>http://www.aboutcode.net/2007/08/27/DataAccessSyntaxUsingAnonymousMethods.aspx</link>
      <pubDate>Mon, 27 Aug 2007 09:41:09 GMT</pubDate>
      <description>&lt;p&gt;
I have so far managed to avoid needing to use any fancy ORM tools. However, this doesn't
mean I like writing all the standard ADO.NET code by hand. Using C# 2.0 anonymous
methods I am able to write code like the following. (I'm not sure all of this is truly
original work; if you have already done this&amp;nbsp;then sweet! I just want to share
the ideas with everyone.)
&lt;/p&gt;
&lt;p&gt;
Customer c = With.Database&amp;lt;Customer&amp;gt;(delegate(Database db)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; return db.ExecuteReader&amp;lt;Customer&amp;gt;(&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "select Id, FirstName, Surname from Customer
where Id = @id", // The SQL to execute&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; delegate(IDbCommand cmd) // This anonymous
function is called before executing so we can add params.&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; db.AddParameter(cmd,
"@id", DbType.Int32, id);&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; delegate(IDataReader reader) //&amp;nbsp;The
IDataReader&amp;nbsp;returned from&amp;nbsp;ExecuteReader is passed here.&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; if (reader.Read())&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;
return new Customer(&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;
reader.GetInt32(0),&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;
reader.GetString(1),&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;
reader.GetString(2));&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; else&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;
return null;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; });&lt;br&gt;
}); 
&lt;p&gt;
My Database class manages the creation of a connection and optionally a transaction.
It then exposes methods to invoke SQL commands (Reader, Scalar and NonQuery). A transaction
can be automatically provided by calling With.DatabaseInTransaction( ... ) instead.
This then wraps the inputted action in a try-catch-finally block, commit and rolling
back in the usual places.
&lt;/p&gt;
&lt;p&gt;
("With" is a static class that provides convenient access to the Database object) 
&lt;p&gt;
public static T DatabaseInTransaction&amp;lt;T&amp;gt;(Function&amp;lt;Database, T&amp;gt; function)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; using (Database db = new Database())&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; db.BeginTransaction();&lt;br&gt;
&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; {&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; T result = function(db);&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; db.CommitTransaction();&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 result;&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; catch&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; db.RollbackTransaction();&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; throw;&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; }&lt;br&gt;
} 
&lt;p&gt;
There are generic and non-generic versions of the functions, depending on if we want
to return a value. 
&lt;p&gt;
For example, here is the non-generic ExecuteReader method from Database: 
&lt;p&gt;
public void ExecuteReader(string sql, Action&amp;lt;IDbCommand&amp;gt; addParameters, Action&amp;lt;IDataReader&amp;gt;
action)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Debug.Assert(sql != null, "sql cannot be null.");&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Debug.Assert(action != null, "action cannot be null."); 
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; using (IDbCommand cmd = CreateCommand(sql))&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (addParameters != null)&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; addParameters(cmd);&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; using (IDataReader reader = cmd.ExecuteReader())&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; action(reader);&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; }&lt;br&gt;
} 
&lt;p&gt;
The IDbCommand is created using the following method. Notice that we also handle assigning
the transaction if we're in one.
&lt;/p&gt;
&lt;p&gt;
IDbCommand CreateCommand(string sql)&lt;br&gt;
{&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; Debug.Assert(_connection != null &amp;amp;&amp;amp; _connection.State ==
ConnectionState.Open); 
&lt;p&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; IDbCommand cmd = _connection.CreateCommand();&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; cmd.CommandText = sql;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; cmd.CommandType = CommandType.Text;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; if (_transaction != null)&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; cmd.Transaction = _transaction;&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; return cmd;&lt;br&gt;
} 
&lt;p&gt;
The Database class implements IDisposable, thus allowing the "using" syntax in the
With class methods. In Dispose() I close the connection, if the transaction is still
open&amp;nbsp;I rollback first.
&lt;/p&gt;
&lt;p&gt;
I anyone wants the full Database and With classes drop me a line. I'm looking forward
to C# 3.0 since the improved type inference and lambda syntax will slim down the amount
of keyboard time even more!
&lt;/p&gt;
&lt;img width="0" height="0" src="http://www.aboutcode.net/aggbug.ashx?id=d9660556-29e4-4b45-b420-d42ef678d63e" /&gt;</description>
      <comments>http://www.aboutcode.net/CommentView,guid,d9660556-29e4-4b45-b420-d42ef678d63e.aspx</comments>
      <category>.net</category>
      <category>c#</category>
      <category>data_access</category>
      <category>programming</category>
      <category>syntax</category>
    </item>
  </channel>
</rss>