那么,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 的高級部分進行講解,比如對查詢前后的事件支持,查詢結果自動轉換為對象/集合。不過這種比較代碼性的東西,的確比較難閱讀,也讓我異常糾結。
額,好像很多人想覺得我這款博客皮膚不錯?其實這一款博客皮膚是參考 李寶亨達人 的博客風格進行改版的,很感謝他的皮膚(他是綠色版,我是藍色版)。
我很懶,但如果您在使用這套組件中遇見任何問題或者有任何建議意見,可以在博客留言,我將會及時回復。源碼已更新。稍后上傳。
