Login or Sign Up to become a member!
LessThanDot Sit Logo

LessThanDot

Desktop Developer

Less Than Dot is a community of passionate IT professionals and enthusiasts dedicated to sharing technical knowledge, experience, and assistance. Inside you will find reference materials, interesting technical discussions, and expert tips and commentary. Once you register for an account you will have immediate access to the forums and all past articles and commentaries.

LTD Social Sitings

Lessthandot twitter Lessthandot Linkedin Lessthandot friendfeed Lessthandot facebook Lessthandot rss

Note: Watch for social icons on posts by your favorite authors to follow their postings on these and other social sites.

Your profile

Authors

Search

XML Feeds

Google Ads

« Microsoft Source Analysis for C# AnnouncedUnused references »
comments
Rate Post:
submit to reddit Digg!FacebookDotnetkicks

Coming from a database background, I should’ve known better. But, I didn’t. Recently I found myself needing to write a GUI wrapper for a new Address Standardization component we got at work. This was purchased in order to clean addresses for a variety of data processing tasks we do on the way into the database, allowing us to completely automate these processes, so the DLL I wrote around it was designed with that in mind. Thinking in this mindset, it was a rough transition when I realized that for this GUI to work, I needed to read the information I need in from a database (in this case primarily MS Access), fix the addresses, and write it back.

Luckily I had already added a class to the .dll with the sole purpose of being used in mapping between database (or flat file) columns and fields expected by the address standardization tool, so that part was partly done for me (good thinking, Alex!). However, I also wrote the program to use a bare-bones .dll that I use for data access, and I was sending the queries generated by the application back through a method designed to execute a single query. The app worked, and performance was actually acceptable when using a SQL Server database, but when using an access database it was S-L-O-W. Luckily I remembered a recent discussion on a forum that shall not be named, where someone brought up how slow opening and closing access connections was for them, so I was able to identify that as the bottleneck right away.

My solution was to add an overload for the function that runs the single SQL Statement. Now, in addition to a string, it can also take an enum indicating whether it is the first transaction in a batch (and therefore a connection needs to be opened and transaction initialized), somewhere in the middle, or the last (so the transaction needs to be committed and the connection closed). It makes writing the calling code a bit more difficult, as you need to handle the first and last rows a bit differently, but after implementing this change, the application worked an astounding 10x faster against an access database. And more impressive (to me anyway) 4-6x faster than the commercial product we had used for this in the past!

Here is some code for an example:

  1. public Object RunSQL(String sql, Enums.TransactionState tranState)
  2. {
  3.     IDbCommand cmd;
  4.  
  5.     try
  6.     {
  7.         if (tranState == Enums.TransactionState.Begin)
  8.         {
  9.             _connDb.Open();
  10.             _tran = _connDb.BeginTransaction();
  11.         }
  12.  
  13.         cmd = new OleDbCommand(sql, _connDb, _tran);
  14.  
  15.         return cmd.ExecuteNonQuery();
  16.     }
  17.     catch (Exception ex)
  18.     {
  19.         throw ex;
  20.     }
  21.     finally
  22.     {
  23.         if (tranState == Enums.TransactionState.Commit)
  24.         {
  25.             _tran.Commit();
  26.             _connDb.Close();
  27.             _tran = null;
  28.         }
  29.  
  30.         cmd = null;
  31.     }
  32. }

and the Enum (pretty straightforward, but just in case):

  1. public enum TransactionState
  2. {
  3.     /// <summary>
  4.     /// Open a new transaction
  5.     /// </summary>
  6.     Begin,
  7.     /// <summary>
  8.     /// Continue using open transaction
  9.     /// </summary>
  10.     Continue,
  11.     /// <summary>
  12.     /// Commit transaction when finished
  13.     /// </summary>
  14.     Commit
  15. }

So now hopefully you can avoid the embarassing mistake of failing to batch your queries properly. One would think a “database guy” would know better :oops:

Well, he does now!

About the Author

Alex is a .net and SQL Server developer from southeastern PA, where he lives with a lovely fiance and a veritable smorgasbord of pets. He's also working on a masters degree in Software Engineering. He loves mountain biking, home brewing, and the mono runtime.
Social SitingsTwitterHomePageLTD RSS Feed
1781 views
c#, database
submit to reddit Digg!FacebookDotnetkicks

Comments and Feedback

2 comments

Comment from: chopstik [Member] Email
****-
Out of curiosity, Alex, what is the address standardization tool that you use(d)? I could have used this sort of thing in my previous life...
03/24/09 @ 07:36
Comment from: AlexCuse [Member] Email
The old one was called Mailers+4 (Melissa Data), the new one was Mailroom Toolkit Architect (Satori Software). Melissa Data offered a library to use in automation but it was more expensive, and its' API didn't seem as rich. Its' been a while though, probably worth another look.
07/06/09 @ 10:03

Leave a comment


Your email address will not be revealed on this site.

Your URL will be displayed.
(Line breaks become <br />)
(Name, email & website)
(Allow users to contact you through a message form (your email will not be revealed.)