Av rating:
Total votes: 52
Total comments: 17


Amirthalingam Prasanna
ADO.NET 2.0 Factory Classes
25 October 2005

Achieve database independence by developing a pluggable data layer

This article explains how to use .NET 2.0’s data provider factory classes to develop a pluggable data layer that is independent of database type and ADO.NET data provider.

Introduction

If you want to develop a data layer that supports many types of database products, it should not be tightly coupled with a particular database product or ADO.NET data provider. The fact that ADO.NET has data providers that are enhanced for specific databases makes that independence more difficult and cumbersome to achieve.

You should have a good understanding of the .NET framework and familiarity with the ADO.NET library before using .NET 2.0’s data provider factory classes to create a pluggable data layer.

Supporting many database products

If you plan to market your application to many potential clients, it should support more than one database product. Since some clients may have already invested in a particular database, the ability to easily configure your application to work with different products is a strong feature.

When developing a data-centric application, I generally use a particular ADO.NET data provider and develop the data layer targeting a particular database product. One benefit of isolating the data layer is that it makes it easy to change the database product without affecting the application too much.

If the business and user interface layers in your application use the data layer for database-related operations and do not directly access the database, then you can have multiple data layers for the database products you want to support. Although this approach sounds reasonable, maintaining multiple data layers for every database product you intend to support is not feasible. The classes in System.Data.Common namespace enable you to build a data layer independent of the database product, and easily change the database product on which it works.

System.Data.Common namespace

Take the following ADO.NET code that connects to a SQL Server database and execute an arbitrary SQL statement:

C# Code

System.Data.SqlClient.SqlConnection con = new 
System.Data.SqlClient.SqlConnection();
con.ConnectionString = "Data Source=.;initial
catalog=Northwind;Integrated security=true";
System.Data.SqlClient.SqlCommand cmd = new
System.Data.SqlClient.SqlCommand();
cmd.CommandText = "Update Products set UnitsInStock=UnitsInStock+10";
cmd.Connection = con;
con.Open();
cmd.ExecuteNonQuery();
con.Close();

There are quite a few problems in the code above that would make it difficult to modify to work with a different database product. One obvious change that is needed is to move the hard-coded connection string information out to a configuration file. Another problem is that we are tying our code to a particular ADO.NET data provider, in this case the SQL Client data provider. This increases the changes that are needed if we want to support another database product.

Now let us see how the code is changed after we move the connection string out to the application configuration file and use the classes in the System.Data.Common namespace instead of the SQL Client ADO.NET data provider:

C# Code

System.Configuration.AppSettingsReader appReader = new 
System.Configuration.AppSettingsReader();
string provider = appReader.GetValue("provider", typeof(string)).ToString();
string connectionString = appReader.GetValue("connectionString",
typeof(string)).ToString();
System.Data.Common.DbProviderFactory factory =
System.Data.Common.DbProviderFactories.GetFactory(provider);
System.Data.Common.DbConnection con = factory.CreateConnection();
con.ConnectionString = connectionString;
System.Data.Common.DbCommand cmd = factory.CreateCommand();
cmd.CommandText = "Update Products set UnitsInStock=UnitsInStock+10″;
cmd.Connection = con;
con.Open();
cmd.ExecuteNonQuery();
con.Close();

App.config file

<configuration> 
  <appsettings>
    <add key = "provider" value ="System.Data.SqlClient"/>
    <add key = "connectionString" value ="Data Source=.;
initial catalog=Northwind;Integrated security=true" /> 
  </appsettings>
</configuration>  

In the code above, other than isolating the connection string, we have used the common ADO.NET data provider in the System.Data.Common namespace. This is a simple implementation of the abstract factory pattern. Each ADO.NET data provider has a factory class that enables us to create ADO.NET objects of its provider type.

The SQL Client ADO.NET data provider, for example, has a SqlClientFactory that can be used to create SqlConnection, SqlCommand, and other SQL Client ADO.NET data provider-specific objects. Based on the string value that is passed to the GetFactory method of the DbProviderFactories class, a concrete instance of a particular ADO.NET data provider factory will be created. Instead of creating the connection and the command objects directly, we use this factory instance to create the necessary ADO.NET objects for us.

The code above shows that we are passing the string value System.Data.SqlClient from the application configuration file, indicating that we want a SqlClientFactory object to be created and assigned to the factory variable. From that point on, all the create methods of the DbProviderFactory object will create ADO.NET objects of the SQL Client ADO.NET data provider.

The classes in ADO.NET have been altered from .NET 1.1 to inherit common base classes from the SystemData.Common namespace. ADO.NET connection classes such as SqlConnection and OleDbConnection inherit from the DbConnection class, for example. The following diagram shows the inheritance hierarchy of the factory classes and the ADO.NET classes:

Provided we have used standard SQL statements, we can easily make our product work with a different ADO.NET data provider by changing the provider in the application configuration file. If we set it to System.Data.OleDb, an OleDbFactory class will be created, which will create OleDb data provider-specific ADO.NET objects such as OleDbConnection and so on.

You might also want to list all of the available ADO.NET data providers. You can do so using the GetFactoryClasses method of the DbProviderFactories class:

C# Code

 DataTable tbl = 
System.Data.CommonDbProviderFactories.GetFactoryClasses();
dataGridView1.DataSource = tbl;
foreach (DataRow row in tbl.Rows)
{
  Console.WriteLine(row["InvariantName"].ToString());
}

 

The GetFactoryClasses method returns a data table containing information about the available ADO.NET data providers. The InvariantName column provides the necessary string value needed to pass to the GetFactory method in order to create a factory for a particular ADO.NET data provider.

One disadvantage of using the factory classes and developing a common data layer is that it limits us to standard SQL statements. This means we cannot take advantage of the full functionality of a particular database product.

One way to overcome this is to make a check on the type of ADO.NET object created by a factory and execute some statements based on it. Though it’s not an elegant approach, it is useful when we need to execute database product-specific SQL statements. For example:

C# Code

DbProviderFactory factory = 
DbProviderFactories.GetFactory("System.Data.SqlClient");
DbCommand cmd = factory.CreateCommand();
if(cmd is System.Data.SqlClient.SqlCommand)
{
  //set command text to SQL Server specific statement
}
else if (cmd is System.Data.OleDb.OleDbCommand)
{
  //set command text to OleDb specific statement
}

Conclusion

The ADO.NET data providers in .NET 2.0 provide factory and common ADO.NET classes that make it easy to keep your code independent from a particular ADO.NET data provider or database product.



This article has been viewed 23034 times.
Amirthalingam Prasanna

Author profile: Amirthalingam Prasanna

Prasanna is a software engineer, technical author and trainer with over 7 years experience in the software development industry. He is a Microsoft MVP in the Visual developer category, a MCT and a MCPD on enterprise application development. You can read his blog at www.prasanna.ws and e-mail him at feedback@prasanna.ws

Search for other articles by Amirthalingam Prasanna

Rate this article:   Avg rating: from a total of 52 votes.


Poor

OK

Good

Great

Must read
 
Have Your Say
Do you have an opinion on this article? Then add your comment below:
You must be logged in to post to this forum

Click here to log in.


Subject: Good One
Posted by: Anonymous (not signed in)
Posted on: Wednesday, November 08, 2006 at 5:16 AM
Message: Actually I had written my own factory class to support different databases. This article really gave me good info about utilizing 2.0 framework inbuilt support.

Thanks,
Srushti.

Subject: Factory classes
Posted by: Anonymous (not signed in)
Posted on: Saturday, January 27, 2007 at 2:57 AM
Message: This article is very good.

Subject: Very Good Concept
Posted by: Anonymous (not signed in)
Posted on: Tuesday, March 20, 2007 at 5:01 AM
Message: Before reading this article, i had not imagined, that it may be possible. This implementation certainly improve extensibility of my application.

Thanks,

Subject: Good concept
Posted by: Anonymous (not signed in)
Posted on: Wednesday, April 25, 2007 at 1:40 AM
Message: It is very useful. I implementend this concept in my project. It is very very good and flexibal.

Subject: Good one
Posted by: bharat songire (not signed in)
Posted on: Monday, June 11, 2007 at 1:26 AM
Message: you help lot to me to understand the exact flow.

Subject: Flexible implementation!
Posted by: Anonymous (not signed in)
Posted on: Wednesday, August 15, 2007 at 10:53 AM
Message: This article is really very awesome and helpful.
But there are some interfaces in ADO.Net that allow to us to using multiple databases like IDBConnection , IDbCommand ...
There is an article that discuss DAL on aspalliance
http://aspalliance.com/837
Please may explain the diffrence between the two method?
Thank you very much

Subject: Excelent!!!
Posted by: Anonymous (not signed in)
Posted on: Friday, September 07, 2007 at 12:12 AM
Message: This article is like water in desert, because it ´s very difficult find an example of database independent in .net. It ´s very easy to understand and to develope.

Thanks a lot!

Subject: complicated sqls
Posted by: Anonymous (not signed in)
Posted on: Tuesday, October 09, 2007 at 3:39 AM
Message: Very nice article. I'll use it inspide that in my project there almost all sql's dependent on dbms.
So in that case it wont be really plugable.:)
Thanks a lot

Subject: Very nice
Posted by: MIHIR (not signed in)
Posted on: Friday, March 14, 2008 at 3:57 AM
Message: Up to that point i was having idea about patterns but i was not able to map it with my code...
But now i have...
Thanks

Subject: Simple and to the point
Posted by: Anonymous (not signed in)
Posted on: Thursday, March 20, 2008 at 1:44 AM
Message: Nicely written and gives a stating point for diving into framework/Patterns.

Subject: Gud and Great
Posted by: Suresh babu (not signed in)
Posted on: Tuesday, April 15, 2008 at 2:14 AM
Message: It gave me a good idea on database independent application. Thanks a lot. Keep continue ...

Subject: Perfect points..
Posted by: Senthilkumar M (not signed in)
Posted on: Friday, April 25, 2008 at 12:18 PM
Message: It gives a brief idea about the DbFactory classes. I Thank you.

Subject: Thanks....
Posted by: Nirmalya (not signed in)
Posted on: Monday, May 05, 2008 at 2:32 AM
Message: Nice article.

Subject: Great article...
Posted by: Anonymous (not signed in)
Posted on: Monday, July 07, 2008 at 4:55 AM
Message: If you are new to patterns, especially Factory patterns (Abstract factory and Factory method) this article is a must read. It shows how object creation is hidden inside the factory and how well you can use Abstract factory and factory method pattern together. Good effort... keep it up.

Subject: Excellent one !!!!
Posted by: Chandru (view profile)
Posted on: Thursday, July 10, 2008 at 6:22 AM
Message: This is really a good one and helpful.It gives clear picture about ADO.net factory usage

Subject: An article well laid out
Posted by: Suresh Beniwal (not signed in)
Posted on: Tuesday, July 29, 2008 at 7:51 AM
Message: Thanks Prasanna.
That was a great insight into ado.net database independence.
Suresh
http://sureshbeniwal.blogspot.com

Subject: need more breif help regarding this concept
Posted by: santosh (view profile)
Posted on: Monday, August 11, 2008 at 8:45 AM
Message: hi prasanna......really it is very nice article.......but if you elaborate a little bit more, then it will be more helpful.. thanxx any way providing useful information.

 






recommended site pinvoke

PInvoke.net is a user-driven wiki which provides .NET developers with native method signatures, so they don't have to spend time writing them from scratch.





Damon Armstrong
Customizing the Login Page in SharePoint 2007
 Damon shows how a few simple steps lead you to being able to include the login form in a consistent look and feel to...  Read more...


ANTS Profiler and the Un-Rest Cure
 After a while, successful applications can get set in their ways. Bart Read and Andrew Hunter decided... Read more...

Silverlight-Speed Loop
 John Bower steps up a gear, produces a Lamborghini, and examines the process of using a high-speed... Read more...

Sid: Vicious
 Dan Archer documents his epic struggle with an apparently simple task of authenticating user... Read more...

Embedding Help so it will be used
 It is not good enough to make assumptions about the way that users go about getting help when they use... Read more...

Optimising a High-Performance Computing Tool
 Many computer systems nowadays have their ‘correctness’ checked using sample testing, but this isn't... Read more...

A Complete URL Rewriting Solution for ASP.NET 2.0
 Ever wondered whether it's possible to create neater URLS, free of bulky Query String parameters?... Read more...

.NET Application Architecture: the Data Access Layer
 Find out how to design a robust data access layer for your .NET applications. Read more...

Web Parts in ASP.NET 2.0
 Most Web Parts implementations allow users to create a single portal page where they can personalize... Read more...

Visual Studio Setup - projects and custom actions
 This article describes the kinds of custom actions that can be used in your Visual Studio setup project. Read more...

Beginning ASP.NET 2.0
 It seems that there is both excitement and confusion surrounding Master Pages and Themes. A big part of... Read more...

Over 150,000 Microsoft professionals subscribe to the Simple-Talk technical journal. Join today, it's fast, simple, free and secure.

Join Simple Talk