Sofire v1.0 开源——快速数据库访问模式 Sofire.Data(2)

Sofire Suite 是一套个人从 2009 年 08 月开始着手研发的套件。历经几年的不断优化改进,从最初的 V 套件到 Sofire2011 到目前的 Sofire.v1.0,Sofire 已经经历了许多项目的考验,并且出色的完成它的使命。现在,我将这套组件再次重构,尝试让它成为任意平台、框架、套件的的底层首选。秉着开源精神,希望这套组件在博友的讨论中不断成长、成熟。

那么,Sofire.v1.0包含什么内容?

下载地址:Sofire.v1.0-120604

1、数据库访问(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):

 

Sofire.Data
数据库是如何连接的?

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 的高级部分进行讲解,比如对查询前后的事件支持,查询结果自动转换为对象/集合。不过这种比较代码性的东西,的确比较难阅读,也让我异常纠结。

额,好像很多人想觉得我这款博客皮肤不错?其实这一款博客皮肤是参考 李宝亨达人 的博客风格进行改版的,很感谢他的皮肤(他是绿色版,我是蓝色版)。

我很懒,但如果您在使用这套组件中遇见任何问题或者有任何建议意见,可以在博客留言,我将会及时回复。源码已更新。稍后上传。

posted @   Treenew Lyn  阅读(3360)  评论(34编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· Apache Tomcat RCE漏洞复现(CVE-2025-24813)
点击右上角即可分享
微信分享提示