Click here to Skip to main content
15,891,828 members
Articles / Database Development / SQL Server

Versatile and Extendible Data Access Factory

Rate me:
Please Sign up or sign in to vote.
2.67/5 (3 votes)
17 Jul 20042 min read 40.6K   459   27  
Using and extending the data access classes, and runtime selection and instantiation using a factory and XML configuration file.
using System;
using System.Data;
using System.Configuration;


#if XML_EXAMPLE_FILE

This is a copy of the XML file, DataSourceInfo.xml, used to test the application.

The XML Schema for ConnectionNames MUST follow this format.

Each distinct connection type must have a corresponding entry (record) in the 
connectionName table.  A record in the connectionName table table is
denoted by the tag <ConnectionName> XML tag as follows:
A. <ConnectionName>
	This tag denotes the begining of a 'record' in the ConnectionName
	'table'.  As required in XML, the tag must also be closed properly
	with the </ConnectionName> end tag.  Several sub tags or 'columns' 
	are required for each record, including <SettingName>, <ObjectType>, 
	and <DetailIndex>.  Each required tag is described below.
	1. <SettingName>
		This is the name by which the application will reference for
		all its information.
	2. <ObjectType>
		This is the fully qualified class name that identifies the object to 
		be created for the connection.  It has the format 'Class name, Assembly
		name'.  You can create your own classes and have them created by using its
		class name here.  Note that all classes used here are child classes of the
		base class DataAccessBase.
	3. <DetailIndex>
		This is used to lookup details of the object's initialization parameters.
		The index points to a "parameter" or "initialization" table contained in
		this XML file.  The initialization table name is derived from the first part
		of the ObjectType value.  For example the ObjectTab 
		<ObjectType>OracleDAO, DAL</ObjectTag> would have an initialization table
		present in this XML file named OracleDAO.
		The initialization table is used for gathering parameters because
		of the non-homogenous nature of the name(s) and how many parameters are 
		required.  For example, Oracle has an entirely different set of parameter
		names as compared with SQLServer.  Section(s) below have more details about
		these 'parameter' tables which are referenced by the DetailIndex field.

As mentioned above, each <ConnectionName> must reference a record in a table that
contains a list of initialization parameters and their values.  The initialization
table name is determined by the value in the <ObjectType> tag described above.
Therefore, each ObjectType can have kind-of a free-form set of parameter/value pairs
which are enclosed in a tag of the object type.

****************** Start of XML File *********************
****************** Start of XML File *********************

<?xml version="1.0" standalone="yes"?>
<ConnectionInformation>
  <ConnectionName>
    <SettingName>UIConnection</SettingName>
    <Description>Data source for UI</Description>
    <ObjectType>SQLServerDAO, DAL</ObjectType>
    <DetailIndex>1</DetailIndex>
  </ConnectionName>
  <OracleDAO>
    <ObjectType>Oracle</ObjectType>
    <DetailIndex>1</DetailIndex>
    <userID>MyOracleSchemaGoesHere</userID>
    <Password>MyOraclePasswordGoesHere</Password>
    <DataSource>MyOracleDataSourceGoesHere</DataSource>
  </OracleDAO>
  <SQLServerDAO>
    <ObjectType>SQLServer</ObjectType>
    <DetailIndex>1</DetailIndex>
    <server>(local)</server>
    <Database>GeoWarehouses</Database>
    <Trusted_Connection>yes</Trusted_Connection>
  </SQLServerDAO>
</ConnectionInformation>

****************** End of XML File *********************
****************** End of XML File *********************

#endif


namespace TestDAL
{
	/// <summary>
	/// Summary description for Class1.
	/// </summary>
	class EntryPoint 
	{		
		[STAThread]
		static void Main(string[] args) 
		{
			//Define (declare and set memory aside) a factory object 
			// that takes care of creating and returning
			// a reference to the correct data access object type.
			DataAccessFactory myDBFactory = new DataAccessFactory();

			//Declair a variable capable of being any DAO object type
			DataAccessBase myDBObj;

			//Define a object (locally defined) that will help
			// with the dirty chores of setting properties of
			// the factory.  This object is not necessary, but just
			// helps abstract out unnecessary details used in this
			// particular test.
			try 
			{
				factoryHelper factoryProperties;
				if (args.Length >= 1)
					factoryProperties = new factoryHelper(args[0]);
				else 
					factoryProperties = new factoryHelper();

				myDBFactory.ObjectTypeToCreate = factoryProperties.getDaoObjectType;
				myDBFactory.ObjectSetupIndex = factoryProperties.getIndex;
				myDBFactory.ConfigFileName = factoryProperties.getXMLFileName;
			}
			catch (Exception e)
			{
				Console.WriteLine ("Problem in Factory Helper");
				Console.WriteLine ("Message: " + e.Message);
				Console.WriteLine ("Source: " + e.Source);
				return;
			} 

			try
			{
				//Use the factory to instantiate the appropriate type of
				// DAO object.  Assign the object to the base class object.
				myDBObj = myDBFactory.CreateVendorDAO();

				//Use the DAO object to generate an return a dataset based on
				// a user supplied query.
				string strSQL = "select * from customers";
				if (args.Length >= 2) strSQL = args[1];
				DataSet resultsDS = myDBObj.getDataSet(strSQL);

				//Write the results of the query.
				WriteDBRecords(resultsDS);
			}
			catch (Exception e)
			{
				//Catch and report any problems.
				Console.WriteLine ("Found prblem.");
				Console.WriteLine("Error message: [{0}]", e.Message);
				Console.WriteLine("Source [{0}]", e.Source);
			}
		}

		/// <summary>
		/// Writes records to the console.
		/// </summary>
		/// <param name="dSet"></param>
		static private void WriteDBRecords (DataSet dSet)
		{
			foreach  (DataColumn c in dSet.Tables[0].Columns)
			{
				Console.Write (c.ColumnName + "\t");
			}
			Console.WriteLine("");
				
			foreach (DataRow r in dSet.Tables[0].Rows)
			{
				foreach  (DataColumn c in dSet.Tables[0].Columns)
				{
					Console.Write (r[c] + "\t");
				}
				Console.WriteLine("");
			}
		}
	}

	/// <summary>
	/// Abstracts out the dirty work / nitty gritty of reading the xml file and 
	/// provides easy access to xml file elements.
	/// </summary>
	public class factoryHelper
	{
		private DataSet dsConnObjSetup;
		private DataRow[] rows;
		private string connectionName = "UIConnection";
		private string xmlFileName = System.IO.Directory.GetCurrentDirectory() + 
					ConfigurationSettings.AppSettings["XMLConfigFileName"];
		
		public int getIndex
		{
			get
			{
				return int.Parse (rows[0]["DetailIndex"].ToString());
			}
		}

		public string getDaoObjectType
		{
			get
			{
				return rows[0]["ObjectType"].ToString();
			}
		}

		public string getXMLFileName
		{
			get
			{
				return xmlFileName;
			}
		}
		

		public factoryHelper()
		{
			InitObject();
		}
		public factoryHelper (string connName)
		{
			connectionName = connName;
			InitObject();
		}

		private void InitObject ()
		{
			dsConnObjSetup = new DataSet();

			try
			{
				dsConnObjSetup.ReadXml (xmlFileName);
			}
			catch (Exception e)
			{
				throw new ArgumentException(
							string.Format("Problem reading XML file [{0}]\n.Net Exception [{1}]", xmlFileName, e.Message) );
			}

			rows = dsConnObjSetup.Tables["ConnectionName"].
				Select("SettingName = '" + connectionName + "'");

			if (rows.GetUpperBound(0) != 0)
			{
				throw new ArgumentException (string.Format(
					"Cannot find setting {0} in file {1}", connectionName, 
					xmlFileName));
			}
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions