那么,Sofire.v1.0包含什么內容?
下載地址:Sofire.v1.0-1206041、數據庫訪問(Sofire.Data)
2、快速動態反射(Sofire.Dynamic)
3、高效簡短的二進制序列化(Sofire.Serialization.BinarySuite)
4、遠程對象模式(Sofire.DataComm.Remote)
5、安全高效Socket(Sofire.DataComm.Net)
6、面向切面(Sofire.AOP)
7、等。由於Sofire v1.0 第一期移植,故而功能暫時尚未全部移植完成。
緊接上篇內容《Sofire v1.0 開源——WinForm/SL/WebForm 的 Remoting(1)》。
本文主要講述 SOFIRE 框架在底層開發中,采用 Sofire.Data 對各種數據庫的操作進行統一使用。它仿佛就是對 ADO.NET 的全面封裝。
當然,Sofire.Data 支持哪些數據庫,關鍵是在於實現,而不是在於“支持不支持”,理論上所有基於 ADO.NET 的數據庫全部支持,而其他數據庫,也有部分支持。
當前所支持的數據庫包括:MSSQL、Oracle、Oracle、DDTekOracle、OleDb 和 SQLite。至於其他的數據庫(如 MySql),由於本人實際項目中並沒使用這些數據庫,所有暫時不支持,如果你想支持其他數據庫,請繼承 Sofire.Data.QueryEngineBase。
public DataTable GetTotalReport(string username, DateTime begin, DateTime end) { //處理過程... return new DataTable(); }
當然,這並不是指責這樣的寫法的好壞,而是建議對函數的返回值進行適當的封裝描述。例如,我可以這樣:
public Result<DataTable> GetTotalReport(string username, DateTime begin, DateTime end) { try { //處理過程... return new DataTable(); } catch(Exception ex) { return ex; } }
通過這樣的約定,可以明確的告訴函數調用者,這個函數返回一個值,但這個操作函數也可能會返回一個錯誤的內容。
當遇到具有返回內容的操作函數時,可以這樣的處理返回結果
public void Test() { var r = this.GetTotalReport("a", DateTime.Now, DateTime.Now); if(r.IsSucceed) { DataTable table = r.Value; } else { Exception ex = r.Exception; } }
簡單的代碼,表述了返回值具備了函數操作結果的“正確性”,同時也提供了錯誤的詳細信息。以下是返回結果的接口(IResult):
/// <summary> /// 表示一個結果(接口)。 /// </summary> public interface IResult { #region Properties /// <summary> /// 獲取執行時發生的錯誤。 /// </summary> Exception Exception { get; } /// <summary> /// 獲取一個值,表示執行結果是否為失敗。 /// </summary> bool IsFailed { get; } /// <summary> /// 獲取一個值,表示執行結果是否為忽略。 /// </summary> bool IsIgnored { get; } /// <summary> /// 獲取一個值,表示執行結果是否為成功。 /// </summary> bool IsSucceed { get; } /// <summary> /// 獲取執行的狀態。 /// </summary> ResultState State { get; } #endregion Properties #region Methods /// <summary> /// 指定錯誤信息,將當前結果切換到失敗的狀態。 /// </summary> void ToFailded(Exception exception); /// <summary> /// 指定錯誤信息,將當前結果切換到失敗的狀態。 /// </summary> void ToFailded(string exceptionMessage); /// <summary> /// 將當前結果切換到忽略的狀態。 /// </summary> void ToIgnored(); /// <summary> /// 將當前結果切換到成功的狀態,並且清除結果的錯誤信息。 /// </summary> void ToSuccessed(); /// <summary> /// 指示一個結果,與當前結果進行校驗。如果 <paramref name="result"/> 是一個錯誤結果,那么當前的結果將會轉換為錯誤狀態。否則將會轉換 <paramref name="result"/> 的狀態。 /// </summary> /// <param name="result">比較的結果。</param> /// <returns>返回一個值,表示結果是否為成功狀態。</returns> bool Checking(Result result); #endregion Methods } /// <summary> /// 表示包含一個返回值的結果(接口)。 /// </summary> /// <typeparam name="TValue">返回值的類型。</typeparam> public interface IResult<TValue> : IResult { #region Properties /// <summary> /// 設置或獲取結果的返回值。若結果不處於成功的狀態,將返回默認值。 /// </summary> TValue Value { get; set; } #endregion Properties #region Methods /// <summary> /// 將當前結果切換到成功的狀態,並且清除結果的錯誤信息。 /// </summary> /// <param name="value">結果返回的值。</param> void ToSuccessed(TValue value); /// <summary> /// 指示一個結果,與當前結果進行校驗。如果 <paramref name="result"/> 是一個錯誤結果,那么當前的結果將會轉換為錯誤狀態。否則將會轉換 <paramref name="result"/> 的狀態。 /// </summary> /// <param name="result">比較的結果。</param> /// <param name="value">狀態為成功時的返回值。</param> /// <returns>返回一個值,表示結果是否為成功狀態。</returns> bool Checking(Result result, TValue value); #endregion Methods } /// <summary> /// 表示包含兩個返回值的結果(接口)。 /// </summary> /// <typeparam name="TValue1">第一個返回值的類型。</typeparam> /// <typeparam name="TValue2">第二個返回值的類型。</typeparam> public interface IResult<TValue1, TValue2> : IResult { #region Properties /// <summary> /// 設置或獲取結果的第一個返回值。若結果不處於成功的狀態,將返回默認值。 /// </summary> TValue1 Value1 { get; set; } /// <summary> /// 設置或獲取結果的第二個返回值。若結果不處於成功的狀態,將返回默認值。 /// </summary> TValue2 Value2 { get; set; } #endregion Properties #region Methods /// <summary> /// 將當前結果切換到成功的狀態,並且清除結果的錯誤信息。 /// </summary> /// <param name="value1">結果的第一個返回值。</param> /// <param name="value2">結果的第二個返回值。</param> void ToSuccessed(TValue1 value1, TValue2 value2); /// <summary> /// 指示一個結果,與當前結果進行校驗。如果 <paramref name="result"/> 是一個錯誤結果,那么當前的結果將會轉換為錯誤狀態。否則將會轉換 <paramref name="result"/> 的狀態。 /// </summary> /// <param name="result">比較的結果。</param> /// <param name="value1">狀態為成功時的第一個返回值。</param> /// <param name="value2">狀態為成功時的第二個返回值。</param> /// <returns>返回一個值,表示結果是否為成功狀態。</returns> bool Checking(Result result, TValue1 value1, TValue2 value2); #endregion Methods }
Sofire.Data 的所有數據庫實現,都派生於 Sofire.Data.QueryEngineBase,通過簡單的幾個抽象實現,從而達到對數據庫的快速支持。
public void DataConnect() { string connectionString = ""; OracleQuery oracleQuery = new OracleQuery(connectionString); // 微軟已經不建議使用這種方式連接 Oracle DDTekOracleQuery oleDbQuery = new DDTekOracleQuery(connectionString); MsSqlQuery mssqlQuery = new MsSqlQuery(connectionString); OleDbQuery oleDbQuery = new OleDbQuery(connectionString); SQLiteQuery sqliteQuery = new SQLiteQuery(connectionString); // 派生基類 QueryEngineBase 擴展,可以對更多的數據庫提供支持。 }
數據庫的查詢
public void Execute() { string connectionString = ""; int uid = 1; DDTekOracleQuery oracleQuery = new DDTekOracleQuery(connectionString); TableResult r1 = oracleQuery.ExecuteTable("SELECT * FROM Users WHERE UID=:uid", "uid", uid); if(r1.IsSucceed) { DataTable table = r1.Value; } SqlQuery mssqlQuery = new SqlQuery(connectionString); TableResult r2 = mssqlQuery.ExecuteTable("SELECT * FROM Users WHERE UID=@uid", "@uid", uid); if(r2.IsSucceed) { DataTable table = r2.Value; } }
當然,上面的演示代碼僅僅是返回一張表,更多的支持請參考以下圖片
由於今年的工作關系,我對 Oracle 的接觸頻繁,Sofire.Data 中對於 Oracle 的支持,也逐漸成熟中,例如支持多行 ExecuteNoQuery,支持游標參數。
private Result Test1() { //“>”符號表示這是一個存儲過程,或程序包 // PKG_FLOW_NAME.UP_GetFlowNameById 的返回值在於一個游標參數。 var tableResult = query.ExecuteTable(">PKG_FLOW_NAME.UP_GetFlowNameById" , new ExecuteParameter("v_FID", 111, DbType.VarNumeric) , query.CreateCursor("c")); if(tableResult.IsSucceed) { Console.WriteLine(tableResult.Value.Rows.Count); } return tableResult; } private Result Test2() { var noQueryResult = query.ExecuteNoQuery(@"begin insert into table1 select * from XXX; insert into table2 select * from XXX; insert into table3 select * from XXX; insert into table4 select * from XXX; end;"); if(tableResult.IsSucceed) { Console.WriteLine(tableResult.Value.Rows.Count); } return tableResult; }
由於時間的關系(最近工作崗位變動),最重要,也是這套框架元老級組件——數據庫部分,介紹的並不詳細。接下來,可能對 Sofire.Data 的高級部分進行講解,比如對查詢前后的事件支持,查詢結果自動轉換為對象/集合。不過這種比較代碼性的東西,的確比較難閱讀,也讓我異常糾結。
額,好像很多人想覺得我這款博客皮膚不錯?其實這一款博客皮膚是參考 李寶亨達人 的博客風格進行改版的,很感謝他的皮膚(他是綠色版,我是藍色版)。
我很懶,但如果您在使用這套組件中遇見任何問題或者有任何建議意見,可以在博客留言,我將會及時回復。源碼已更新。稍后上傳。