統一資料訪問(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/// <summary>/// 資料訪問提供者/資料訪問器。/// </summary>public interface IDataAccessor{ /// <summary> /// 擷取或設定資料訪問環境。 /// </summary> IDataConnection DataConnection { get;set;} /// <summary> /// 執行指定的非查詢命令。 /// </summary> /// <param name="commandString">要執行的命令語句。該語句必須是標準的資料庫語句。</param> /// <returns>返回命令影響的行數。</returns> int Execute(string commandString); /// <summary> /// 執行指定的非查詢命令。 /// </summary> /// <param name="commandString">要執行的命令語句。該語句必須是標準的資料庫語句。</param> /// <param name="parameters">要執行的命令的參數集合。</param> /// <returns>返回命令影響的行數。</returns> int Execute(string commandString, ParameterCollection parameters); /// <summary> /// 執行指定的非查詢命令。 /// </summary> /// <param name="commandString">要執行的命令語句。該語句必須是標準的資料庫語句。</param> /// <param name="commandType">要執行的命令類型。</param> /// <returns>返回命令影響的行數。</returns> int Execute(string commandString, System.Data.CommandType commandType); /// <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); /// <summary> /// 執行指定的非查詢命令。 /// </summary> /// <param name="command">要執行的資料庫訪問命令。該命令必須是有效資料庫訪問參數的封裝。</param> /// <returns>返回命令影響的行數。</returns> int Execute(DbCommand command); /// <summary> /// 執行給定的資料庫查詢命令。 /// </summary> /// <param name="commandString">要執行的命令語句,可能是select語句,也可能是預存程序名稱。</param> /// <returns>返回查詢到的資料結果。</returns> object Query(string commandString); /// <summary> /// 執行給定的資料庫查詢命令。 /// </summary> /// <param name="commandString">要執行的命令語句,可能是select語句,也可能是預存程序名稱。</param> /// <param name="resultType">調用方要求的返回結果的類型。</param> /// <param name="fillParameters">當結果類型為DataSet、DataTable、或者Xml時的OleDbDataAdapter 的填充參數,其他ResultType 忽略該參數。</param> /// <returns>返回查詢到的資料結果。</returns> object Query(string commandString, EAS.Data.Access.ResultType resultType, params object[] fillParameters); /// <summary> /// 執行給定的資料庫查詢命令。 /// </summary> /// <param name="commandString">要執行的命令語句,可能是select語句,也可能是預存程序名稱。</param> /// <param name="parameters">命令執行需要的參數。</param> /// <returns>返回查詢到的資料結果。</returns> object Query(string commandString, ParameterCollection parameters); /// <summary> /// 執行給定的資料庫查詢命令。 /// </summary> /// <param name="commandString">要執行的命令語句,可能是select語句,也可能是預存程序名稱。</param> /// <param name="parameters">命令執行需要的參數。</param> /// <param name="resultType">調用方要求的返回結果的類型。</param> /// <returns>返回查詢到的資料結果。</returns> object Query(string commandString, ParameterCollection parameters, EAS.Data.Access.ResultType resultType); /// <summary> /// 執行給定的資料庫查詢命令。 /// </summary> /// <param name="commandString">要執行的命令語句,可能是select語句,也可能是預存程序名稱。</param> /// <param name="commandType">要執行的命令的類型。</param> /// <param name="parameters">命令執行需要的參數。</param> /// <param name="resultType">調用方要求的返回結果的類型。</param> /// <param name="fillParameters">當結果類型為DataSet、DataTable、或者Xml時的OleDbDataAdapter 的填充參數,其他ResultType 忽略該參數。</param> /// <returns>返回查詢到的資料結果。</returns> object Query(string commandString, System.Data.CommandType commandType, ParameterCollection parameters, EAS.Data.Access.ResultType resultType, params object[] fillParameters); /// <summary> /// 執行給定的資料庫查詢命令。 /// </summary> /// <param name="command">要執行的資料庫訪問命令。該命令必須是有效資料庫訪問參數的封裝,可能是select語句,也可能是預存程序名稱。</param> /// <returns>返回查詢到的資料結果。</returns> object Query(DbCommand command); /// <summary> /// 執行指定的非查詢命令(批處理指示)。 /// </summary> /// <param name="commands">要執行的資料庫訪問命令集合。該命令集合必須是有效資料庫訪問參數的封裝。</param> /// <returns>返回命令影響的行數。</returns> int BachExecute(DbCommandCollection commands); /// <summary> /// 執行給定的資料庫查詢命令集合(批查詢指令)。 /// </summary> /// <param name="commands">要執行的資料庫訪問命令集合。該命令必須是有效資料庫訪問參數的封裝,可能是select語句,也可能是預存程序名稱。</param> /// <returns>返回查詢到的資料結果集合。</returns> /// </remarks> EAS.Data.Access.DbResultCollection BackQuery(DbCommandCollection commands); /// <summary> /// 在事務環境中執行給定的EAS.Data.Access.TransactionHandler,該EAS.Data.Access.TransactionHandler中包括了要在事務中執行的所有資料庫操作。 /// </summary> /// <param name="handler">要執行的EAS.Data.Access.TransactionHandler 對象。</param> /// <returns>返回受影響的行數,該值為EAS.Data.Access.TransactionHandler 返回的結果,預設返回0。</returns> int TransactionExecute(EAS.Data.Access.TransactionHandler handler); /// <summary> /// 委託查詢。當調用方需要返回DataReader時,如果使用Query,則必須自行開啟環境和關閉環境以及DataReader的關閉。 /// 調用方可以將處理DataReader結果的程式碼封裝裝在DataReaderHandler委託中,由DelegateQuery方法代表調用方調用資料處理程式,並在DelegateQuery的內部管理資料訪問環境和DataReader的生存周期。 /// </summary> /// <param name="handler">需要由DelegateQuery方法代為調用的EAS.Data.Access.DataReaderHandler委派物件。handler中的方法可以關閉DataReader對象,也可以不關閉DataReader對象。</param> /// <param name="commandString">要執行的查詢命令文本。</param> void DelegateQuery(EAS.Data.Access.DataReaderHandler handler, string commandString); /// <summary> /// 委託查詢。當調用方需要返回DataReader時,如果使用Query,則必須自行開啟環境和關閉環境以及DataReader的關閉。 /// 調用方可以將處理DataReader結果的程式碼封裝裝在DataReaderHandler委託中,由DelegateQuery方法代表調用方調用資料處理程式,並在DelegateQuery的內部管理資料訪問環境和DataReader的生存周期。 /// </summary> /// <param name="handler">需要由DelegateQuery方法代為調用的EAS.Data.Access.DataReaderHandler委派物件。handler中的方法可以關閉DataReader對象,也可以不關閉DataReader對象。</param> /// <param name="commandString">要執行的查詢命令文本。</param> /// <param name="commandType">查詢命令類型。</param> /// <param name="parameters">命令參數。</param> void DelegateQuery(EAS.Data.Access.DataReaderHandler handler, string commandString, System.Data.CommandType commandType, ParameterCollection parameters);}
IDataConnetion:
IDataConnection /// <summary> /// 資料訪問串連/環境。 /// </summary> /// <remarks> /// 本介面是資料訪問的一個基礎介面,用於建設資料訪問串連/環境。 /// </remarks> public interface IDataConnection : EAS.Sessions.ISessionResource { /// <summary> /// 在此串連上建立一個資料訪問器。 /// </summary> /// <returns>成功建立的資料訪問器。</returns> IDataAccessor CreateDataAccessor(); /// <summary> /// 在此串連上建立一個資料訪問器。 /// </summary> /// <returns>成功建立的資料訪問器。</returns> [Obsolete("方法已到期,請使用CreateDataAccessor方法")] IDataAccessor CreateAccessor(); /// <summary> /// 開啟資料連線。 /// </summary> void Open(); /// <summary> /// 關閉資料連線。 /// </summary> void Close(); }}
資料訪問器(IDataAccessor)是統一資料訪問中進行資料存取的介面,他生存於資料庫環境IDataAccessor之中,用戶端只需通過該訪問器提供的方法並為這些方法提供適當的參數進行資料庫操作。訪問器內部自動在當前資料庫連接上建立資料庫命令,並封裝返回的結果。
目前訪問器在傳回查詢結果時,加入了一步裝箱操作,返回統一類型的資料(object),使用者需求使用拆箱,然後得到具體的資料結果。
因為在訪問資料庫時定了一個原則: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);
在資料庫事務這一塊,提供了除正常的開啟事務、關閉事務之後,我更推薦一種事務委託和方式去執行,IDataAccessor提供了TransactionExecute方法,其委託TransactionHandler定義:
/// <summary> /// 定義資料庫操作的交易處理委託。該委託將代表客戶執行資料庫事務,這樣使用者不需要考慮事務的開始和結束。 /// </summary> public delegate int TransactionHandler(IDataAccessor Accessor);
目前實現了SQL資料庫(SQLServerConnection、SQLServerAccessor)、OleDb資料庫(OleDbConnection、OleDbAccessor)、ODBC資料庫(ODBCConnection、ODBCAccessor),ORACLE資料庫由單獨的資料庫訪問服務程式集實現。
具體的資料訪問常式我將在後面展示:
下面來說一下AgileEAS.NET中的ORM。
QQ群:15118502
連結:AgileEAS.NET應用開發平台介紹
AgileEAS.NET之敏捷並行開發方法
敏捷軟體工程實驗室