自http://www.rzrgm.cn/artech/archive/2007/04/03/698755.html 轉(zhuǎn)載
application block應(yīng)達(dá)到的目的:
-
封裝所有的Data Access操作。
-
適合主流的DBMS:SQL Server(2000和2005),Oracle(9i和10g),DB2。
-
盡量簡(jiǎn)化Developer的操作和提供最大的靈活性,在Data Retrieval方面,只要指定SQL或者Stored Procedure和相應(yīng)的參數(shù);在Data Update方面,既可以直接調(diào)用SQL和Stored Procedure,還可以把包含多個(gè)相互關(guān)聯(lián)Data Table的Dataset通過(guò)一次調(diào)用實(shí)現(xiàn)數(shù)據(jù)的更新。此外,可以自由地選擇使用SQL還是Stored procedure;可以使用Commander builder生成Command或者使用基于Mapped stored procedure生成的Command進(jìn)行數(shù)據(jù)更新。
-
實(shí)現(xiàn)泛型編程,使使用該AppBlock的代碼能夠適合所有的數(shù)據(jù)庫(kù)。
-
實(shí)現(xiàn)Transaction。
-
提供可配置性,包括不同數(shù)據(jù)庫(kù)的配置,不同Data Mapping的配置等等。
下面是該AppBlock使用到的Entity:

-
Database:Abstract Class,封裝了絕大部分和具體數(shù)據(jù)庫(kù)無(wú)關(guān)的Data Access操作邏輯。通過(guò)兩個(gè)Mapping:IDbParameterNameMapping和IStoredProcedureNameMapping,實(shí)現(xiàn)Dataset和Db的一個(gè)映射。比如Dataset中Data table name和Stored procedure name的Mapping,Data table中Field和Stored procedure中參數(shù)名的Mapping。這兩個(gè)Mapping是可以配置的,你只需要實(shí)現(xiàn)提供的Interface編寫適合你的Mapping provider就可以了。
-
SqlDatabase:封裝基于SQL Server 的操作。ADO.NET 2.0在1.0的基礎(chǔ)上作了很大的改善,主要的增加的大量的基類,為我們進(jìn)行泛型編程,編寫和具體Db無(wú)關(guān)的代碼變得異常容易。所以我們把大多數(shù)Data Access的操作可以封裝在Abstract Database類中,SqlDatabase中的內(nèi)容實(shí)際上是很少的。
-
OracleDatabase:封裝基于Oracle的操作。
-
IDbParameterNameMapping和IStoredProcedureNameMapping:我想大家都是這樣的感受,實(shí)現(xiàn)ORM的本質(zhì)就是實(shí)現(xiàn)內(nèi)存中的數(shù)據(jù)(主要是Dataset)和數(shù)據(jù)庫(kù)的一個(gè)映射。在Dataset和數(shù)據(jù)庫(kù)中的Table相互Mapping方面,我覺(jué)得沒(méi)有必要采用特殊的Mapping,直接和簡(jiǎn)單易行的就是Table和Dataset中的Data Table完全匹配(table name 和field name完全匹配)。所以重要的是實(shí)現(xiàn)Dataset和Stored procedure的Mapping:Table Name如何與進(jìn)行Insert,Update,Delete的Stored procedure name匹配,不同Version(original & current)的Field如何與Stored procedure的Parameter name 匹配。而這樣一個(gè)匹配應(yīng)該是可配置的,因?yàn)槊總€(gè)Application在數(shù)據(jù)庫(kù)設(shè)計(jì)時(shí)的命名都有各自的要求,所以我在這里采用的Provider的設(shè)計(jì)模式。用戶可以實(shí)現(xiàn)這兩個(gè)Interface編寫適合自己的Mapping provider,通過(guò)我提供的Configuration block很容易地完成配置。同時(shí),我寫了一個(gè)默認(rèn)的,簡(jiǎn)單的Mapping:SimpleDbParameterNameMapping和SimpleStoredProcedureNameMapping。
有一點(diǎn)需要補(bǔ)充的是,要實(shí)現(xiàn)上面的Mapping,對(duì)Stored Procedure的命名有較高的要求,手工編寫的方式已經(jīng)不能適合我們的要求,所以我們需要一個(gè)生成Stored procedure的Generator,這個(gè)Generator也使用這兩個(gè)可配置的Mapping接口。
-
DatabaseFactory: 一個(gè)靜態(tài)的類,根據(jù)配置的信息創(chuàng)建你需要的具體的Database對(duì)象,實(shí)現(xiàn)泛型化編程。
-
DataAccessConfigurationCollection,DataAccessConfigurationElement,DataAccessConfigurationSection 三個(gè)Configuration的Class。
-
為了使大家清楚地看出這個(gè)Application block所有的操作,我把所有的操作封裝在一個(gè)IDatabase的interface中,不過(guò)需要注意的是,我采用的是基于Abstract class的編程,而不是基于Interface的編程,相信大家對(duì)這兩種方式討論得已經(jīng)碰倒的太多了,孰優(yōu)孰劣我就不想對(duì)說(shuō)了。這個(gè)IDatabase 接口,只是展示所有Operation之用,并沒(méi)有在我的代碼中用到。


namespace Artech.ApplicationBlock.DataAccess


{
public interface IDatabase

{

Fill a System.Data.DataSet with retrieved data.#region Fill a System.Data.DataSet with retrieved data.
void FillDataSet(DataSet dataInfo, string commandText, IDictionary<string, object> parameters);

void FillDataSet(DataSet dataInfo, string tableName, string commandText, IDictionary<string, object> parameters);

void FillDataSet(DataSet dataInfo, string tableName, CommandType commandType, string commandText, IDictionary<string, object> parameters);

#endregion


Save the changed data which is stored in a dataset into database.#region Save the changed data which is stored in a dataset into database.
void UpdateData(DataSet dataInfo);

void UpdateData(DataTable table);

void UpdateData(DataTable table, string insertCommandText, string updateCommandText, string deleteCommandText,
Dictionary<string, object> insertParameters, Dictionary<string, object> updateParameters, Dictionary<string, object> deleteParameters);

void UpdateData(DataTable table, CommandType commandType, string insertCommandText, string updateCommandText, string deleteCommandText,
Dictionary<string, object> insertParameters, Dictionary<string, object> updateParameters, Dictionary<string, object> deleteParameters);

void UpdateData(DataTable table, DbCommand insertCommand, DbCommand updateCommand, DbCommand deleteCommand);

#endregion


Execute a command and return the affect row count.#region Execute a command and return the affect row count.
int ExecuteNonQuery(CommandType commandType, string commandText, Dictionary<string, object> inputParameters, Dictionary<string, object> outputParameters);

int ExecuteNonQuery(CommandType commandType, string commandText, Dictionary<string, object> inputParameters);

int ExecuteNonQuery( string commandText, Dictionary<string, object> inputParameters, Dictionary<string, object> outputParameters);

int ExecuteNonQuery( string commandText, Dictionary<string, object> inputParameters);
#endregion


Execute a command and return the data in the form of data reader.#region Execute a command and return the data in the form of data reader.
DbDataReader ExecuteReader(CommandType commandType, string commandText, Dictionary<string, object> inputParameters, Dictionary<string, object> outputParameters);

DbDataReader ExecuteReader(CommandType commandType, string commandText, Dictionary<string, object> inputParameters);

DbDataReader ExecuteReader(string commandText, Dictionary<string, object> inputParameters, Dictionary<string, object> outputParameters);

DbDataReader ExecuteReader(string commandText, Dictionary<string, object> inputParameters);
#endregion


Execute a command and return a scalar value.#region Execute a command and return a scalar value.

object ExecuteScalar(CommandType commandType, string commandText, Dictionary<string, object> inputParameters, Dictionary<string, object> outputParameters);

object ExecuteScalar(CommandType commandType, string commandText, Dictionary<string, object> inputParameters);

object ExecuteScalar(string commandText, Dictionary<string, object> inputParameters, Dictionary<string, object> outputParameters);

object ExecuteScalar(string commandText, Dictionary<string, object> inputParameters);
#endregion


Transaction based operation#region Transaction based operation
void BeginTransaction();
void Commit();
void RollBack();
#endregion
}
}

這個(gè)列表和大部分ORM沒(méi)有什么太大的區(qū)別,大家已經(jīng)司空見(jiàn)慣,實(shí)現(xiàn)起來(lái)也不會(huì)有什么太大的困難。對(duì)于大部分操作,我不會(huì)做詳細(xì)的介紹。接下來(lái)我們來(lái)簡(jiǎn)要地看看這樣一個(gè)AppBlock是如何實(shí)現(xiàn)的。
1. Data Mapping
我們首先來(lái)看看Data Mapping:實(shí)現(xiàn)Dataset中Table name和Stored Procedure Name的Mapping,以及Dataset 中的Field 和Stored procedure的參Parameter name的Mapping。
IDbParameterNameMapping


using System;
using System.Collections.Generic;
using System.Text;

namespace Artech.ApplicationBlock.DataMapping


{

/**//// <summary>
/// IStoredProcedureNameMapping defines the mapping between the data table name and the name of stored procedures to perform insertion, modification and deletion operation.
/// </summary>
public interface IStoredProcedureNameMapping

{

/**//// <summary>
/// Get the name of stored procedure to perform seletion operation.
/// </summary>
/// <param name="tableName">The name of the database table.</param>
/// <returns>The name of stored procedure to perform seletion operation</returns>
string GetSelectStoredProcedureName(string tableName);


/**//// <summary>
/// Get the name of stored procedure to perform insert operation.
/// </summary>
/// <param name="tableName">The name of the database table.</param>
/// <returns>The name of stored procedure to perform insertion operation</returns>
string GetInsertStoredProcedureName(string tableName);


/**//// <summary>
/// Get the name of stored procedure to perform modification operation.
/// </summary>
/// <param name="tableName">The name of the database table.</param>
/// <returns>The name of stored procedure to perform modification operation</returns>
string GetModifyStoredProcedureName(string tableName);


/**//// <summary>
/// Get the name of stored procedure to perform deletion operation.
/// </summary>
/// <param name="tableName">The name of the database table.</param>
/// <returns>The name of stored procedure to perform deletion operation</returns>
string GetDeleteStoredProcedureName(string tableName);
}
}

IDbParameterNameMapping


using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
namespace Artech.ApplicationBlock.DataMapping


{

/**//// <summary>
/// IDbParameterNameMapping define the defult mapping between the source column name and the parameter name of the corresponding stored procedure.
/// </summary>
public interface IDbParameterNameMapping

{

/**//// <summary>
/// Get the source column name based on the parameter name of the related stored procedure.
/// </summary>
/// <param name="patameterName">The parameter name of the corresponding stored procedure.</param>
/// <returns>The source column name corresponding to the parameter name.</returns>
string GetSourceCoulmnName(string patameterName);


/**//// <summary>
/// Get the source parameter name based on the source column name.
/// </summary>
/// <param name="columnName">The source column name corresponding to the parameter name.</param>
/// <param name="rowVersion">The data row version of the source solumn conressponding to the parameter.</param>
/// <returns>The parameter name of the corresponding stored procedure.</returns>
string GetParameterName(string columnName, DataRowVersion rowVersion);
}
}

這兩個(gè)Mapping主要用在通過(guò)Dataset跟新數(shù)據(jù)庫(kù)的場(chǎng)景,利用IDbParameterNameMapping,我們通過(guò)Dataset中各個(gè)Table name獲得對(duì)它進(jìn)行Insert,Update,Delete操作的Stored procedure的name。利用IDbParameterNameMapping,我們可以為Stored procedure的Parameter指定對(duì)應(yīng)的Source field.
注:GetParameterName方法實(shí)際上是不需要的,我把使用在另一個(gè)AppBlock中。
接下來(lái)我們來(lái)寫兩個(gè)實(shí)現(xiàn)了上面連個(gè)Interface的默認(rèn)的mapping:SimpleStoredProcedureNameMapping和SimpleDbParameterNameMapping。他實(shí)際上實(shí)現(xiàn)了這樣的Mapping:比如Table name為T_ABC_DEF(我經(jīng)常用的命名方式:以T開(kāi)頭代表Table,名稱大寫并一下劃線連接),那么對(duì)應(yīng)的Stored procedure name分別為:sp_abc_def_s(Select), sp_abc_def_i(Insert), sp_abc_def_u(Update), sp_abc_def_d(delete)。如果Field name為ABC_123,那么對(duì)于Original version的Parameter name為o_abc_123(o代表Original),Current version的Parameter name為p_abc_123(p代表一般意義的Parameter)。


using System;
using System.Collections.Generic;
using System.Text;

namespace Artech.ApplicationBlock.DataMapping


{

/**//// <summary>
/// IStoredProcedureNameMapping defines the mapping between the data table name and the name of stored procedures to perform insertion, modification and deletion operation.
/// </summary>
public class SimpleStoredProcedureNameMapping:IStoredProcedureNameMapping

{

IStoredProcedureNameMapping Members#region IStoredProcedureNameMapping Members

/**//// <summary>
/// Get the name of stored procedure to perform selection operation.
/// </summary>
/// <param name="tableName">The name of the database table.</param>
/// <returns>The name of stored procedure to perform selection operation</returns>
public string GetSelectStoredProcedureName(string tableName)

{
//T_ABC_DEF=>sp_abc_def_s
return string.Format("sp_{0}_s", tableName.Substring(2, tableName.Length - 2).ToLower());
}


/**//// <summary>
/// Get the name of stored procedure to perform insert operation.
/// </summary>
/// <param name="tableName">The name of the database table.</param>
/// <returns>The name of stored procedure to perform insertion operation</returns>
public string GetInsertStoredProcedureName(string tableName)

{
//T_ABC_DEF=>sp_abc_def_i
return string.Format("sp_{0}_i", tableName.Substring(2, tableName.Length - 2).ToLower());
}


/**//// <summary>
/// Get the name of stored procedure to perform modification operation.
/// </summary>
/// <param name="tableName">The name of the database table.</param>
/// <returns>The name of stored procedure to perform modification operation</returns>
public string GetModifyStoredProcedureName(string tableName)

{
//T_ABC_DEF=>sp_abc_def_u
return string.Format("sp_{0}_u", tableName.Substring(2, tableName.Length - 2).ToLower());
}

/**//// <summary>
/// Get the name of stored procedure to perform deletion operation.
/// </summary>
/// <param name="tableName">The name of the database table.</param>
/// <returns>The name of stored procedure to perform deletion operation</returns>
public string GetDeleteStoredProcedureName(string tableName)

{
//T_ABC_DEF=>sp_abc_def_d
return string.Format("sp_{0}_d", tableName.Substring(2, tableName.Length - 2).ToLower());
}

#endregion
}
}

SimpleDbParameterNameMapping


using System;
using System.Collections.Generic;
using System.Text;
using System.Data;

namespace Artech.ApplicationBlock.DataMapping


{

/**//// <summary>
/// SimpleDbParameterNameMapping defines a simple mapping method between the corresponding parameter name and source culumn name of the table.
/// </summary>
public class SimpleDbParameterNameMapping:IDbParameterNameMapping

{

IDbParameterNameMapping Members#region IDbParameterNameMapping Members


/**//// <summary>
/// Get the source column name based on the parameter name of the related stored procedure.
/// </summary>
/// <param name="patameterName">The parameter name of the corresponding stored procedure.</param>
/// <returns>The source column name corresponding to the parameter name.</returns>
public string GetSourceCoulmnName(string patameterName)

{
//@p_abc_def|o_abc_def=>ABC_DEF
return patameterName.Substring(3, patameterName.Length - 3).ToUpper();
}


/**//// <summary>
/// Get the source parameter name based on the source column name.
/// </summary>
/// <param name="columnName">The source column name corresponding to the parameter name.</param>
/// <param name="rowVersion">The data row version of the source solumn conressponding to the parameter.</param>
/// <returns>The parameter name of the corresponding stored procedure.</returns>
public string GetParameterName(string columnName, DataRowVersion rowVersion)

{
//ABC_DEF =>@p_abc_def|o_abc_def
string prefix = "@p";
if (rowVersion == DataRowVersion.Original)

{
prefix = "@o";
}

return string.Format("{0}_{1}", prefix, columnName.ToLowerInvariant());

}

#endregion
}
}

2. Configuration
對(duì)于一個(gè)能夠被不同Application使用的Application Block,可配置性是最基本的要求,為此,我為整個(gè)AppBlock編寫了單獨(dú)的Configuration。在很多情況下我們?cè)谝粋€(gè)Application中會(huì)使用到多個(gè)具有相同或不同類型的數(shù)據(jù)庫(kù),所以這個(gè)Configuration System也許我們配置若干數(shù)據(jù)庫(kù)。因而我充分利于了ConfigurationElementCollection,ConfigurationElementCollection中的每個(gè)Element對(duì)應(yīng)一個(gè)具體的數(shù)據(jù)庫(kù)。相關(guān)的配置信息包括:
-
一個(gè)唯一標(biāo)該識(shí)數(shù)據(jù)庫(kù)的DatabaseName(配置名稱為name)
-
一個(gè)帶面Data access provider類型的DbProvider(配置名稱為dbProvider)
-
每個(gè)Db對(duì)應(yīng)的ConnectionString(配置名稱為connectionString)
-
代表是否是Default Db的IsDefaultDatabase(配置名稱為isDefault)
-
兩個(gè)Mapping :DbParameterNameMapping和StoredProcedureNameMapping(配置名稱為dbParameterNameMapping和storedProcedureNameMapping,默認(rèn)值為我丁一的默認(rèn)Mapping type)
-
默認(rèn)的Command Type:DedaultCommandType(配置名稱為dedaultCommandType,默認(rèn)為使用stored procedure)
-
使用CommandBuilder生成的Command還是使用Mapped stored procedure生成的Command進(jìn)行Update:UsingCommandBuilderToUpdate(配置名稱為usingCommandBuilderToUpdate,默認(rèn)為使用Mapped stored procedure)。
ConfigurationElementCollection


using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;

namespace Artech.ApplicationBlock.Configuration


{
public class DataAccessConfigurationCollection: ConfigurationElementCollection

{
protected override ConfigurationElement CreateNewElement()

{
return new DataAccessConfigurationElement();
}

protected override object GetElementKey(ConfigurationElement element)

{
DataAccessConfigurationElement configurationElement = element as DataAccessConfigurationElement;
if (configurationElement == null)

{
throw new Exception("It is fail to parse the data access configuration");
}

return configurationElement.DatabaseName;
}
}
}

DataAccessConfigurationElement


using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Data;

namespace Artech.ApplicationBlock.Configuration


{
public class DataAccessConfigurationElement:ConfigurationElement

{

/**//// <summary>
/// The database namw which uniquely identifies the current database.
/// </summary>
[ConfigurationProperty("name", IsRequired = true)]
public string DatabaseName

{
get

{
return this["name"] as string;
}

set

{
this["name"] = value;
}
}


/**//// <summary>
/// A string indicating the concrete database provider.
/// </summary>
[ConfigurationProperty("dbProvider", DefaultValue = "System.Data.SqlClient")]
public string DbProvider

{
get

{
return this["dbProvider"] as string;
}

set

{
this["dbProvider"] = value;
}
}


/**//// <summary>
/// A string indicating the connection string to connect to the concrete database.
/// </summary>
[ConfigurationProperty("connectionString")]
public string ConnectionString

{
get

{
return this["connectionString"] as string;
}

set

{
this["connectionString"] = value;
}
}


/**//// <summary>
/// A flag which determines if this is the default database.
/// </summary>
[ConfigurationProperty("isDefault", DefaultValue = false)]
public bool IsDefaultDatabase

{
get

{
return (bool)this["isDefault"];
}

set

{
this["isDefault"] = value;
}
}

/**//// <summary>
/// A bool flag indicating if the default operation are all executed using command builder or stored procedure.
/// </summary>
[ConfigurationProperty("usingCommandBuilderToUpdate", DefaultValue = false)]
public bool UsingCommandBuilderToUpdate

{
get

{
return (bool)this["usingCommandBuilderToUpdate"];
}

set

{
this["usingCommandBuilderToUpdate"] = value;
}
}


/**//// <summary>
/// A CommandType enumeration indicating if the default command type.
/// </summary>
[ConfigurationProperty("dedaultCommandType", DefaultValue = CommandType.StoredProcedure)]
public CommandType DedaultCommandType

{
get

{
return (CommandType)this["dedaultCommandType"];
}
set

{
this["dedaultCommandType"] = value;
}
}


/**//// <summary>
/// A string indicating the type of the class to perform mapping between parameter and the source column name.
/// </summary>
[ConfigurationProperty("dbParameterNameMapping", DefaultValue = "Artech.ApplicationBlock.DataMapping.SimpleDbParameterNameMapping,Artech.ApplicationBlock.DataMapping")]
public string DbParameterNameMapping

{
get

{
return this["dbParameterNameMapping"] as string;
}

set

{
this["dbParameterNameMapping"] = value;
}
}


/**//// <summary>
/// A string indicating the type of the class to perform mapping between the data table name and the name of stored procedures to perform insertion, modification and deletion operation.
/// </summary>
[ConfigurationProperty("storedProcedureNameMapping", DefaultValue = "Artech.ApplicationBlock.DataMapping.SimpleStoredProcedureNameMapping,Artech.ApplicationBlock.DataMapping")]
public string StoredProcedureNameMapping

{
get

{
return this["storedProcedureNameMapping"] as string;
}

set

{
this["storedProcedureNameMapping"] = value;
}
}
}
}

DataAccessConfigurationSection


using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Data;

namespace Artech.ApplicationBlock.Configuration


{
public class DataAccessConfigurationSection: ConfigurationSection

{
[ConfigurationProperty("", IsDefaultCollection = true)]
public DataAccessConfigurationCollection Databases

{
get

{
return this[""] as DataAccessConfigurationCollection;
}

set

{
this[""] = value;
}
}

}
}

我們可以把我們定義的Configure通過(guò)下面的方式運(yùn)用到configuration文件中。
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="Artech.ApplicationBlock" type="Artech.ApplicationBlock.Configuration.ApplicationBlockConfigurationSectionGroup, Artech.ApplicationBlock.Configuration">
<section name="Artech.ApplicationBlock.DataAccess" type="Artech.ApplicationBlock.Configuration.DataAccessConfigurationSection,Artech.ApplicationBlock.Configuration"/>
<section name="Artech.ApplicationBlock.Messaging" type="Artech.ApplicationBlock.Configuration.MessagingConfigurationSection,Artech.ApplicationBlock.Configuration"/>
</sectionGroup>
</configSections>
<Artech.ApplicationBlock>
<Artech.ApplicationBlock.DataAccess>
<add name="sqlDatabase" connectionString="Data Source=JIANGJINNAN\SQLEXPRESS;Initial Catalog=iFramework;Integrated Security=True" ></add>
</Artech.ApplicationBlock.DataAccess>
</Artech.ApplicationBlock>
</configuration>

注:我把我開(kāi)發(fā)的所有AppBlock相關(guān)的Configuration放在一個(gè)自定義的叫做ApplicationBlockConfigurationSectionGroup的ConfigurationSectionGroup中(<sectionGroup name="Artech.ApplicationBlock" type="Artech.ApplicationBlock.Configuration.ApplicationBlockConfigurationSectionGroup, Artech.ApplicationBlock.Configuration">),我推薦大家使用這種方式,一來(lái)可以使結(jié)構(gòu)更加清晰,二來(lái)在你需要的時(shí)候,擴(kuò)展該ConfigurationSectionGroup加入一些公用的配置。
3. Database Factory
為了實(shí)現(xiàn)泛型化的編程,使我的代碼和具體的數(shù)據(jù)庫(kù)無(wú)關(guān),我采用了Factory的模式。我定義了兩個(gè)重載的方法CreateDatabase,調(diào)用沒(méi)有參數(shù)的方法創(chuàng)建一個(gè)默認(rèn)的Database(isDefault=”true”), 調(diào)用有參數(shù)的方法通過(guò)傳入配置的Database的name創(chuàng)建我們需要的Database。具體的邏輯就是通過(guò)ConfigurationManager提取相應(yīng)的Configuration 信息,通過(guò)DbProvider創(chuàng)建對(duì)應(yīng)類型的Database (比如”System.Data.SqlClient”對(duì)應(yīng)SQL Server)。把provider的信息傳入System.Data.Common.DbProviderFactories.GetFactory方法創(chuàng)建一個(gè)System.Data.Common。DbProviderFactory賦值給創(chuàng)建的Database的DatabaseProviderFactory屬性(DbProviderFactory是一個(gè)很有價(jià)值的Type,為我們創(chuàng)建一個(gè)泛型的ADO.NET對(duì)象提供了方便)。同時(shí)把其他的配置信息賦值給創(chuàng)建的Database相應(yīng)的屬性。提取兩個(gè)Mapping Type的信息,通過(guò)Reflection的機(jī)制創(chuàng)建相應(yīng)的類型,并同時(shí)把其他的配置信息賦值給創(chuàng)建的Database相應(yīng)的屬性。


using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.Common;
using System.Reflection;
using System.Configuration;
using Artech.ApplicationBlock.Configuration;
using Artech.ApplicationBlock.Common;
using Artech.ApplicationBlock.DataMapping;
using Artech.ApplicationBlock.Common.Exceptions;

namespace Artech.ApplicationBlock.DataAccess


{
public static class DatabaseFactory

{
static void ThrowAConfigurationException()

{
throw new CustomConfigurationException(CommonConstant.DataAccess.Messages.ConfigurationError);
}

static DatabaseFactory()

{

}


/**//// <summary>
/// Create the default database.
/// </summary>
/// <returns>Default database.</returns>
public static Database CreateDatabase()

{
DataAccessConfigurationElement configurationElement = ApplicationBlockConfiguration.GetDataAccessConfigurationElement();
Database database = null;

if (configurationElement.DbProvider == CommonConstant.DataAccess.ProviderInvariantName_SqlServer)

{
database = new SqlDatabase();
}
else

{
}

database.ConnectionString = configurationElement.ConnectionString;
database.DatabaseProviderFactory = DbProviderFactories.GetFactory(configurationElement.DbProvider);
database.DefaultCommandType = configurationElement.DedaultCommandType;

Type dbParameterNameMappingType = Type.GetType(configurationElement.DbParameterNameMapping);
database.DbParameterNameMapping = (IDbParameterNameMapping)dbParameterNameMappingType.GetConstructor(new Type[0]).Invoke(new object[0]);

Type storedProcedureNameMappingType = Type.GetType(configurationElement.StoredProcedureNameMapping);
database.StoredProcedureNameMapping = (IStoredProcedureNameMapping)storedProcedureNameMappingType.GetConstructor(new Type[0]).Invoke(new object[0]);
database.UseCommandBuilder = configurationElement.UsingCommandBuilderToUpdate;

return database;
}

/**//// <summary>
/// Create a particular database by specifying the configurable database name.
/// </summary>
/// <param name="databaseName">the name of database specified in configuration.</param>
/// <returns>The database corresponding to the database name.</returns>
public static Database CreateDatabase(string databaseName)

{
DataAccessConfigurationElement configurationElement = ApplicationBlockConfiguration.GetDataAccessConfigurationElement(databaseName);
Database database = null;
if (configurationElement.DbProvider == CommonConstant.DataAccess.ProviderInvariantName_SqlServer)

{
database = new SqlDatabase();
}
else

{

}
database.ConnectionString = configurationElement.ConnectionString;
database.DatabaseProviderFactory = DbProviderFactories.GetFactory(configurationElement.DbProvider);
database.DefaultCommandType = configurationElement.DedaultCommandType;

Type dbParameterNameMappingType = Type.GetType(configurationElement.DbParameterNameMapping);
database.DbParameterNameMapping = (IDbParameterNameMapping)dbParameterNameMappingType.GetConstructor(new Type[0]).Invoke(new object[0]);

Type storedProcedureNameMappingType = Type.GetType(configurationElement.StoredProcedureNameMapping);
database.StoredProcedureNameMapping = (IStoredProcedureNameMapping)storedProcedureNameMappingType.GetConstructor(new Type[0]).Invoke(new object[0]);
database.UseCommandBuilder = configurationElement.UsingCommandBuilderToUpdate;

return database;
}
}
}

注:上面的代碼是不完整的,僅僅做到SQL Server的支持,由于基于Configuration的邏輯被我封裝在另一個(gè)Configuration AppBlock中,所以代碼中包含有對(duì)此的調(diào)用,相信不會(huì)影響大家的理解。