統一資料訪問介紹
統一資料訪問(Uniform Data Access,簡寫為UDA)用於隔離系統和資料平台,使系統可以在各種資料庫平台上自由移植。該資料庫提供者要求通過該介面對資料庫進行訪問的模組要提交標準的SQL語句,而不僅僅是對當前資料庫有效語句。
統一資料訪問與資料層分離是相互相成的兩個概念和實踐、統一資料訪問為資料層分離提供資料庫訪問環境及介面的獨立、介面驅動及資料層體繫結構的一致性提供保證。
統一資料訪問內部自動封裝ADO.NET,具體使用何種資料庫則在外部由系統管理員定義在設定檔中。統一資料提供者內部提供對資料庫連接對象、資料命令對象、事務對象等的管理,因此用戶端不需要自己管理這些對象,只需要提交資料庫命令即可。
在UDA中主要的資料結構為“結果資料”。結果資料是資料庫操作的結果的封裝。如果是一個查詢命令,則可能返回一個IDataReader對象、一個DataSet對象、一個DataTable對象、一個IDictionary對象、一個IList對象、一個資料對象(在資料對象管理中定義的資料結構)或者一個單純的結果等,當然使用者可以要求以XML的格式返回資料。
AgileEAS.NET提供了IDataAccessor和IDataConntion兩個介面:
IDataAccessor提供了對資料的操作:查詢結果和執行SQL語句兩種基本操作,同時提供了SQL批處理、代理查詢和事務委託操作,而IDataConnetion相當於為IDataAccessor提供了一個資料庫執行環境。
資料訪問器(IDataAccessor)是統一資料訪問中進行資料存取的介面,他生存於資料庫環境IDataAccessor之中,用戶端只需通過該訪問器提供的方法並為這些方法提供適當的參數進行資料庫操作。訪問器內部自動在當前資料庫連接上建立資料庫命令,並封裝返回的結果。
目前實現了SQL資料庫(SQLServerConnection、SQLServerAccessor)、OleDb資料庫(OleDbConnection、OleDbAccessor)、ODBC資料庫(ODBCConnection、ODBCAccessor),ORACLE資料庫由單獨的資料庫訪問服務程式集實現。
詳解Query和Execute
上面簡單的介紹了UDA及其中最主要的兩個介面,在這兩個介面中,IDataAccessor介面是負責資料操縱業務的,其中定義了最重要的兩個重載方法Query和Execute。
我們來看看Query的重載:
/// <summary>
/// 執行給定的資料庫查詢命令。
/// </summary>
/// <param name="commandString">要執行的命令語句。</param>
/// <param name="commandType">要執行的命令的類型。</param>
/// <param name="parameters">命令執行需要的參數。</param>
/// <param name="resultType">調用方要求的返回結果的類型。</param>
/// <returns>返回查詢到的資料結果。</returns>
object Query(string commandString, System.Data.CommandType commandType, ParameterCollection parameters, EAS.Data.Access.ResultType resultType);
在AgileEAS.NET中Query針對不同的傳回型別只提供一個方法,根據最後一個參數傳回型別返回不同的的查詢結果,於是產生一次裝備操作,上層的調用者需要解決拆箱處理,下面看看傳回型別:
Default:預設。這種類型的結果一般用於返回單個查詢值或者一個彙總值(比如 count、max等的值)。
DataReader:返回一個 IDataReader對象。由於 IDataReader對象資料庫的訪問是連線導向的,而 Query 方法內部符合前面的IConnection操作模式,因此如果要返回一個 IDataReader,則必須在調用 Query 方法前開啟相應的 IConnection,並在對IDataReader操作結束後關閉 IConnection,否則Query方法返回前會關閉 IConnection而導致 IDataReader不可用。可以使用DataReaderHandler委託解決這個問題。
DataSet:返回一個 System.Data.DataSet對象。用於擷取一個非連線導向的資料集合。
DataTable:返回一個System.Data.DataTable對象。用於擷取一個非連線導向的資料集合。
Dictionary:返回一個 IDictionary介面集合對象。用於擷取一個非連線導向的資料庫記錄。記錄的欄位對應到字典的鍵。
List:返回一個 System.Collections.IList對象。用於擷取一個非連線導向的資料庫記錄的集合,每一個記錄只有一個欄位。
接著我們來看看Execute的重載:
/// <summary>
/// 執行指定的非查詢命令。
/// </summary>
/// <param name="commandString">要執行的命令語句。</param>
/// <param name="commandType">要執行的命令類型。</param>
/// <param name="parameters">要執行的命令的參數集合。</param>
/// <returns>返回命令影響的行數。</returns>
int Execute(string commandString, System.Data.CommandType commandType, ParameterCollection parameters);
Execute直接返回查詢所影響的行數。
資料處理過程
AgileEAS.NET平台在訪問資料庫時定了一個原則:IDataAccessor不得隨意變更IDataConnetion的狀態,我們知道在訪問資料庫時需要開啟和關閉資料庫操作,所以在IDataAccessor執行SQL命令過程上,首先判讀IDataConnetion是否開啟,如果未開啟則執行IDataConnetion.Open()並在執行SQL完畢進行IDataConnetion.Close()。
bool open = this.Connection.IsOpen;
if(!open)
this.Connection.Open();
try
{
//執行SQL
}
finally
{
if(!open)
this.Connection.Close();
}
委託查詢
而在執行查詢命令時有一種返回結果IDataReader,這種狀態需要資料庫一直保持開啟狀態,所以我們增加了一個委託方法DelegateQuery,委託DataReaderHandler定義如下:
/// <summary>
/// 定義以DataReader作為結果返回時的資料訪問委託。
/// </summary>
/// <remarks>
/// 該委託的執行個體可以由Accessor.DelegateQuery方法在內部調用,這樣委託執行個體就不需要考慮關閉DataReader的問題。
/// </remarks>
public delegate void DataReaderHandler(System.Data.IDataReader dataReader);
程式員在開發過程中如果需要不處理資料庫開啟和關閉操作而需要返回IDataReader類型的處理結果,可以使用如下形式的處理:
private void button3_Click(object sender, EventArgs e)
{
IDataAccessor dataAccessor = new OleDbConnection().CreateDataAccessor();;
dataAccessor.DelegateQuery(new DataReaderHandler(LoadToUI), "SELECT * FROM Table1");
}
private void LoadToUI(IDataReader reader)
{
while (reader.Read())
{
// 業務代碼
}
}
事務委託
在資料庫事務這一塊,提供了除正常的開啟事務、關閉事務之後,我更推薦一種事務委託和方式去執行,IDataAccessor提供了TransactionExecute方法,其委託TransactionHandler定義:
/// <summary>
/// 定義資料庫操作的交易處理委託。該委託將代表客戶執行資料庫事務,這樣使用者不需要考慮事務的開始和結束。
/// </summary>
public delegate int TransactionHandler(IDataAccessor Accessor);
下面列一個常式:
private void button3_Click(object sender, EventArgs e)
{
IDataAccessor dataAccessor = new OleDbConnection().CreateDataAccessor();;
dataAccessor.TransactionExecute(new TransactionHandler(SaveData));
}
private int SaveData(IDataAccessor accessor)
{
int iAff = 0;
iAff+=accessor.Execute("...");
//
iAff += accessor.Execute("...");
return iAff;
}
擷取UDA對象
UDA中的IDataConnection對象繼承自EAS.Sessions.ISessionResource介面,也就是說UDA中的資料連線也是一種會話資源,可以通過取於上下文提供的會議中讀取:
//取當前會話串連
IDataConnection dbcn = session.Resouces.FindResources(typeof(IDataConnection))[0] as IDataConnection;
//訪問器
IDataAccessor dataAccessor = dataConnection.CreateDataAccessor();
或者直接從上下文環境的IOC容器中直接擷取:
EAS.Objects.IContainer container = ContextHelper.Context.Container;
//取資料連線
IDataConnection dbcn = container.GetServiceComponentInstance(typeof(IDataConnection)) as IDataConnection;
//訪問器
IDataAccessor dataAccessor = dataConnection.CreateDataAccessor();
不同通過何種方式擷取UDA對象,我們都無法在編程時預Crowdsourced Security Testing道他的具體實現,AgileEAS.NET平台實踐著而向介面驅動的思想,UDA對象的具體執行個體類型寫在設定檔中:
<object name="MasterDataAccessor" assembly="EAS.Data" type="EAS.Data.Access.OleDbAccessor" LifestyleType="Singleton">
<property name="Connection" type="object" value="MasterDbConnection" />
</object>
<object name="MasterDbConnection" assembly="EAS.Data" type="EAS.Data.Access.OleDbConnection" LifestyleType="Singleton">
<property name="ConnectionString" type="string" value="Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Password=sa;Initial Catalog=EAS;Data Source=vm2003" />
</object>。
連結
AgileEAS.NET平台開發指南-系列目錄
AgileEAS.NET應用開發平台介紹-文章索引
AgileEAS.NET官方網站
敏捷軟體工程實驗室
QQ群:116773358