<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://weblogs.asp.net/utility/FeedStylesheets/atom.xsl" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><title type="html">Ryan Whitaker</title><subtitle type="html">Dishes of Ryan</subtitle><id>http://weblogs.asp.net/ryanw/atom.aspx</id><link rel="alternate" type="text/html" href="http://weblogs.asp.net/ryanw/default.aspx" /><link rel="self" type="application/atom+xml" href="http://weblogs.asp.net/ryanw/atom.aspx" /><generator uri="http://communityserver.org" version="3.0.20510.895">Community Server</generator><updated>2004-10-21T13:03:00Z</updated><entry><title>Transactions with TableAdapters, a lazy man's approach</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/ryanw/archive/2006/03/30/441529.aspx" /><id>http://weblogs.asp.net/ryanw/archive/2006/03/30/441529.aspx</id><published>2006-03-30T20:14:00Z</published><updated>2006-03-30T20:14:00Z</updated><content type="html">&lt;p&gt;If you've used TableAdapters, you'll know that their ability to deal with transactions leaves a little to be desired.&amp;nbsp; Little?&amp;nbsp; Did I say "little"?&amp;nbsp; I mean "a lot".&lt;/p&gt; &lt;p&gt;&lt;a href="http://codebetter.com/blogs/sahil.malik/archive/2005/10/19/133309.aspx"&gt;Sahil Malik has a good slew of advice for people wanting to use transactions with TableAdapters.&lt;/a&gt;&amp;nbsp; Most people will probably just wrap everything up in a TransactionScope and be done with it, which is fine if you're not running a high-traffic site.&amp;nbsp; In doing this, you'll run into the annoyance of the transaction being promoted to the DTC, which is an expensive bit of "bling" to tango with.&lt;/p&gt; &lt;p&gt;For the people that don't like the whole promotion to DTC thing, they'll probably extend their TableAdapter's partial class and add a BeginTransaction method similar to what Sahil proposes.&lt;/p&gt; &lt;p&gt;For me, who's looking at a bajillion TableAdapters, with quite a few of those needing to operate within the scope of a transaction, I instead choose to play the Hacky card and just set the transaction on the TableAdapter's commands through a little bit of reflection.&amp;nbsp; Some may throw your hands up in the air on this.&amp;nbsp; I, however, love it, as it fits my purposes like a latex glove.&lt;/p&gt; &lt;p&gt;The code follows for my so-called TableAdapterHelper.&lt;/p&gt; &lt;p&gt;&lt;code&gt;using System;&lt;br /&gt;using System.Data;&lt;br /&gt;using System.Data.SqlClient;&lt;br /&gt;using System.Reflection;&lt;br /&gt;&lt;/code&gt;&lt;code&gt;&lt;br /&gt;public class TableAdapterHelper&lt;br /&gt;{&lt;br /&gt;public static SqlTransaction BeginTransaction(object tableAdapter)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return BeginTransaction(tableAdapter, IsolationLevel.ReadUncommitted);&lt;br /&gt;}&lt;/code&gt;&lt;/p&gt; &lt;p&gt;&lt;code&gt;public static SqlTransaction BeginTransaction(object tableAdapter, IsolationLevel isolationLevel)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // get the table adapter's type&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Type type = tableAdapter.GetType();&lt;/code&gt;&lt;/p&gt; &lt;p&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // get the connection on the adapter&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SqlConnection connection = GetConnection(tableAdapter);&lt;/code&gt;&lt;/p&gt; &lt;p&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // make sure connection is open to start the transaction&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (connection.State == ConnectionState.Closed)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;code&gt;connection.Open();&lt;/code&gt;&lt;/p&gt; &lt;p&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // start a transaction on the connection&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SqlTransaction transaction = connection.BeginTransaction(isolationLevel);&lt;/code&gt;&lt;/p&gt; &lt;p&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // set the transaction on the table adapter&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SetTransaction(tableAdapter, transaction);&lt;/code&gt;&lt;/p&gt; &lt;p&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return transaction;&lt;br /&gt;}&lt;/code&gt;&lt;/p&gt; &lt;p&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;/// Gets the connection from the specified table adapter.&lt;br /&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;private static SqlConnection GetConnection(object tableAdapter)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Type type = tableAdapter.GetType();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PropertyInfo connectionProperty = type.GetProperty("Connection", BindingFlags.NonPublic | BindingFlags.Instance);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SqlConnection connection = (SqlConnection)connectionProperty.GetValue(tableAdapter, null);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return connection;&lt;br /&gt;}&lt;/code&gt;&lt;/p&gt; &lt;p&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;/// Sets the connection on the specified table adapter.&lt;br /&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;private static void SetConnection(object tableAdapter, SqlConnection connection)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Type type = tableAdapter.GetType();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PropertyInfo connectionProperty = type.GetProperty("Connection", BindingFlags.NonPublic | BindingFlags.Instance);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; connectionProperty.SetValue(tableAdapter, connection, null);&lt;br /&gt;}&lt;/code&gt;&lt;/p&gt; &lt;p&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;/// Enlists the table adapter in a transaction.&lt;br /&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;public static void SetTransaction(object tableAdapter, SqlTransaction transaction)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // get the table adapter's type&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Type type = tableAdapter.GetType();&lt;/code&gt;&lt;/p&gt; &lt;p&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // set the transaction on each command in the adapter&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PropertyInfo commandsProperty = type.GetProperty("CommandCollection", BindingFlags.NonPublic | BindingFlags.Instance);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SqlCommand[] commands = (SqlCommand[])commandsProperty.GetValue(tableAdapter, null);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (SqlCommand command in commands)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; command.Transaction = transaction;&lt;/code&gt;&lt;/p&gt; &lt;p&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // set the connection on the table adapter&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SetConnection(tableAdapter, transaction.Connection);&lt;br /&gt;}&lt;br /&gt;}&lt;/code&gt;&lt;/p&gt; &lt;p&gt;Here's some example usage of the helper methods above.&amp;nbsp; In this example, we have some work that spans two different adapters that we need to enclose in a transaction.&lt;/p&gt; &lt;p&gt;&lt;code&gt;SqlTransaction transaction = null;&lt;br /&gt;&lt;br /&gt;try&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; using (FooTableAdapter fooAdapter = new FooTableAdapter())&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; transaction = TableAdapterHelper.BeginTransaction(fooAdapter);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; fooAdapter.DoSomething();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; using (BarTableAdapter barAdapter = new BarTableAdapter())&lt;br /&gt;&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;TableAdapterHelper.SetTransaction(barAdapter, transaction);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; barAdapter.DoSomething();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; transaction.Commit();&lt;br /&gt;}&lt;br /&gt;catch&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; transaction.Rollback();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw;&lt;br /&gt;}&lt;br /&gt;finally&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; transaction.Dispose();&lt;br /&gt;}&lt;/code&gt;&lt;/p&gt; &lt;p&gt;So, what are the disadvantages here?&amp;nbsp; We're using reflection so there's no compile-time checking nor is there any strong-typing action going on.&amp;nbsp; Using reflection is obviously slower execution-wise&amp;nbsp;than extending your TableAdapter's class.&amp;nbsp; Also, the code-gen implementation of your TableAdapter class could theoretically change if VS2005 gets patched in the future and would therefore cause your TableAdapterHelper to break.&lt;/p&gt; &lt;p&gt;What are the advantages?&amp;nbsp; Compile-time checking, schmompile-schmime checking.&amp;nbsp; Reflection is eons faster than a promotion to DTC, and this approach is certainly faster than extending your TableAdapter classes by hand.&amp;nbsp; And, the code-gen implementation of your TableAdapter class is unlikely to change.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=441529" width="1" height="1"&gt;</content><author><name>RyanW</name><uri>http://weblogs.asp.net/members/RyanW.aspx</uri></author><category term="Programming" scheme="http://weblogs.asp.net/ryanw/archive/tags/Programming/default.aspx" /></entry><entry><title>Modify data before it's inserted in SQL Server 2000/2005</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/ryanw/archive/2006/02/02/437242.aspx" /><id>http://weblogs.asp.net/ryanw/archive/2006/02/02/437242.aspx</id><published>2006-02-03T05:48:00Z</published><updated>2006-02-03T05:48:00Z</updated><content type="html">&lt;p&gt;I had a scenario where I needed to massage some data in this one particular column before it got inserted into the database.&lt;/p&gt; &lt;p&gt;I usually like to implement this kind of logic alongside its business brethren, leaving as much business brouhaha out of the raw database as possible, but in this case I was straddling two apps.&amp;nbsp; One old one, one new one, both using the same database.&amp;nbsp; Problem was, I didn't want to pull down the old code from the Vault, recompile, and post a newish-old version.&amp;nbsp; Long story short, I implemented an INSTEAD OF trigger on the table to massage the data before it got inserted.&amp;nbsp; Boom, data massage for both apps.&lt;/p&gt; &lt;p&gt;&lt;code&gt;/* This trigger makes sure that the data being inserted into&lt;br /&gt;&amp;nbsp;&amp;nbsp; the BarColumn column starts with a dash.&amp;nbsp; If it doesn't, it &lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;/code&gt;&lt;code&gt;will prepend one.&amp;nbsp;*/&lt;/code&gt;&lt;/p&gt; &lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;CREATE TRIGGER FooTable_Insert ON dbo.FooTable&lt;br /&gt;INSTEAD OF INSERT&lt;br /&gt;AS&lt;br /&gt;DECLARE @BarColumn varchar(50)&lt;br /&gt;SET @BarColumn = (SELECT BarColumn FROM INSERTED)&lt;br /&gt;IF (LEFT(@BarColumn, 1) &amp;lt;&amp;gt; '-')&lt;br /&gt;BEGIN&lt;/code&gt;&lt;code&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SET @BarColumn = '-' + @BarColumn&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SELECT *&amp;nbsp;INTO #Inserted FROM Inserted&lt;br /&gt;&lt;/code&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; UPDATE #Inserted SET BarColumn = @BarColumn&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; INSERT INTO FooTable SELECT * FROM #Inserted&lt;br /&gt;END&lt;br /&gt;ELSE&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; INSERT INTO FooTable SELECT * FROM Inserted&lt;/code&gt;&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=437242" width="1" height="1"&gt;</content><author><name>RyanW</name><uri>http://weblogs.asp.net/members/RyanW.aspx</uri></author><category term="Programming" scheme="http://weblogs.asp.net/ryanw/archive/tags/Programming/default.aspx" /></entry><entry><title>Highly performant, caching image resizer?</title><link rel="alternate" type="text/html" href="http://weblogs.asp.net/ryanw/archive/2004/10/21/245822.aspx" /><id>http://weblogs.asp.net/ryanw/archive/2004/10/21/245822.aspx</id><published>2004-10-21T18:03:00Z</published><updated>2004-10-21T18:03:00Z</updated><content type="html">&lt;p&gt;I'm in the ocean in a life ring, somebody please pull me out!&lt;/p&gt; &lt;p&gt;We have a client whose website gets a &lt;em&gt;lot&lt;/em&gt; of traffic.&amp;nbsp; Lots of product images.&amp;nbsp; Lots of image resizing going on.&lt;/p&gt; &lt;p&gt;What I need is a highly performant, .NET-based image resizer.&amp;nbsp; It needs to cache the resized images to disk so it doesn't have to resize every time the page loads.&amp;nbsp; Optionally, it'd be ideal if it supported varying image resizing algorithms.&amp;nbsp; And it'd be great if I could adjust the quality level.&lt;/p&gt; &lt;p&gt;For the past three years, I've used &lt;a href="http://www.unitedbinary.com"&gt;United Binary&lt;/a&gt;'s &lt;a href="http://www.unitedbinary.com/AutoImageSize.aspx"&gt;AutoImageSize&lt;/a&gt; component.&amp;nbsp; When it works, it's fantastic.&amp;nbsp; But, it crashes like nobody's business.&amp;nbsp; And nothing hurts &lt;em&gt;my&lt;/em&gt; business like a component that crashes like nobody's business.&lt;/p&gt; &lt;p&gt;Anyone have any ideas?&amp;nbsp; &lt;/p&gt; &lt;p&gt;(Besides rolling my own using the uber-easy .NET framework.&amp;nbsp; I don't have time.)&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=245822" width="1" height="1"&gt;</content><author><name>RyanW</name><uri>http://weblogs.asp.net/members/RyanW.aspx</uri></author><category term="Programming" scheme="http://weblogs.asp.net/ryanw/archive/tags/Programming/default.aspx" /></entry></feed>
