Simplify your life, abstract wherever possible.

I don't know about you but when I'm coding with I frequently find myself doing the same things over and over.  One of those things that used to drive me crazy with .Net was retrieving a table from the database and doing something with it.  I come from the classic asp world where it 'seemed' much more straight forward than it is in .Net...seems like the code count is higher...anyway it bugged me.  I heard about Enterprise Library's Data Access Application Block and decided to check it out. Better...code count got cut by a couple lines, but still not idiot proof (a design consideration, since I'll be it's only user). So I scoured the web, learned a lot from great programmers like Jean Paul Boodhoo (who's DNRTv series about Patterns inspired the following methods...inspired is a weak word...I blatantly pinched most of this from him but did tweak it a little (especially the SqlParameters part)).  Now when I want a DataTable I can call it as easily as this:

If I have a need to use tSQL I can do this:

DataTable MyDataTable = gateway.ExecuteSqlStatementDataTable("select * from Product_Categories");

Or if I have a need to use a stored procedure I can do this: 

DataTable MyDataTable = gateway.ExecuteSqlSP("dbo.usp_GetProductCategories");

That's it...one line blammo.  If I have a stored procedure with parameters it gets a little more codey but still pretty easy I just have to create an array of sql parameters:

SqlParameter[] sqp = new SqlParameter[2]; // the number here represents the number of parameters.
sqp[0] = new SqlParameter("@param1name",SqlDbType.Int);
sqp[0].Value = 35;
sqp[1] = new SqlParameter("@param2name",SqlDbType.VarChar);
sqp[1].Value = "some text";
DataTable MyDataTable = gateway.ExecuteSqlSP(sqp, "dbo.usp_SomeStoredProcedure");

 This is accomplished with the use of the Enterprise Library DAAB and the gateway pattern. Here's how to get this up and running:

First make sure your web.config or app.config has the following sections:

<configuration>

<configSections>

<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />

</configSections>

<dataConfiguration defaultDatabase="Connection String" />

<connectionStrings>

<add name="Connection String" connectionString="Data Source=myserver;Initial Catalog=mydatabase;Persist Security Info=True;User ID=dbusername;Password=xxxxxx"

providerName="System.Data.SqlClient" /> </connectionStrings>

</configuration>

Second: Make sure your project has the following references (for the DAAB part of this solution):
Microsoft.Practices.EnterpriseLibrary.Common
Microsoft.Practices.EnterpriseLibrary.Data

Third: Make your gateway class.  Here's mine in it's entirety:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.EnterpriseLibrary.Data.Sql;
using System.Data.Common;
using System.Data;
using System.Data.SqlClient;

namespace ApplicationLibrary
{
    public class DbGateway

    {

        public DataTable ExecuteSqlSP(string spname)
        {
          
            Database db = DatabaseFactory.CreateDatabase();
            using (DbCommand dbCommand = db.GetStoredProcCommand(spname))
            {
                using (DataSet myds = db.ExecuteDataSet(dbCommand))
                {
                    return myds.Tables[0].Copy();
                }
            }
           

        }

 

        public DataTable ExecuteSqlSP(SqlParameter[] parms, string spname)
        {
          
            Database db = DatabaseFactory.CreateDatabase();
            using (DbCommand dbCommand = db.GetStoredProcCommand(spname))
            {
                foreach (SqlParameter sqp in parms)
                {
                    dbCommand.Parameters.Add(sqp);
                }

                using (DataSet myds = db.ExecuteDataSet(dbCommand))
                {
                 return myds.Tables[0].Copy();
                }

            }
           
           

        }


        public DataTable ExecuteSqlStatementDataTable(string sqlstatementstring)
        {
          
            Database db = DatabaseFactory.CreateDatabase();
            using (DbCommand dbCommand = db.GetSqlStringCommand(sqlstatementstring))
            {
             using (DataSet myds = db.ExecuteDataSet(dbCommand))
                {
                 return  myds.Tables[0].Copy();
                }
            }
                     
           

        }
    }
}

Fourth: Implement and use:

What I like to do is make a private insance in the class I'm using so right after my class declaration I'd do:

private DbGateway gateway = new DbGateway();

Now in the methods of that class I can use gateway over and over like you saw in the examples at the top.

Where to go from here:
One of the first things I can see people wanting to do is return the DataSet and not just the table (in the event there are many tables in the set).  I think you can see where that'd be pretty easy.

I hope you found this article helpful.  If you have any suggestions on changes or tweaks please feel free to leave a comment.

Special Thanks:
Jean Paul Boodhoo, Svante (from the asp.net forums) and Dot Net Rocks and DnrTV. (If you don't listen to either of those casts you are missing out my friend).

Published Tuesday, January 29, 2008 10:15 AM by ryansjedi
Filed under: ,

Comments

# re: Simplify your life, abstract wherever possible.@ Tuesday, January 29, 2008 5:14 PM

Small fix...in my zealous attempt to keep my production names out of the post I had the wrong method names in the top part of the sample.

# re: Simplify your life, abstract wherever possible.@ Tuesday, January 29, 2008 5:22 PM

Hello,

Could you please explain why you are returning Tables[0].Copy() rather than just Tables[0]?

Thanks

by SteveG

# re: Simplify your life, abstract wherever possible.@ Tuesday, January 29, 2008 5:46 PM

Since DataSet and DataTable implement IDisposable and I'm using them in a "using statement" if I return just Tables[0] it will return the reference to the disposed DataSet, while this won't fail the application it won't allow the Garbage Collector to clean up properly.  That is at least that's how I understand it, I have to admit though that I haven't really done and exhaustive examination of the GC yet.

by Ryan

# re: Simplify your life, abstract wherever possible.@ Wednesday, January 28, 2009 4:11 PM

I'm having a hard time believing you posted this code as a working example.

by Andy

# re: Simplify your life, abstract wherever possible.@ Wednesday, January 28, 2009 4:25 PM

public class DbGateway

   {

       public DataTable ExecuteSqlSP(string spname)

       {

           Database db = DatabaseFactory.CreateDatabase();

           using (SqlCommand sqlCommand = new SqlCommand())

           {

               db.GetStoredProcCommand(spname);

               using (DataSet myds = new DataSet())

               {

                   db.ExecuteDataSet(sqlCommand);

                   return myds.Tables[0];

               }

           }

       }

       public DataTable ExecuteSqlSP(string spname, SqlParameter[] parms)

       {

           Database db = DatabaseFactory.CreateDatabase();

           using (SqlCommand sqlCommand = new SqlCommand())

           {

               db.GetStoredProcCommand(spname, parms);

               using (DataSet myds = new DataSet())

               {

                   db.ExecuteDataSet(sqlCommand);

                   return myds.Tables[0];

               }

           }

       }

   }

by Andy

# re: Simplify your life, abstract wherever possible.@ Wednesday, April 11, 2012 10:47 AM

Лучшие трипы, ЛСД, DXM, и другие галлюциногены, читаем и упарываемся вместе tor4.su/.../viewforum.php

Leave a Comment

(required) 
(required) 
(optional)
(required)