XYS.DataFactory 3.1.1

dotnet add package XYS.DataFactory --version 3.1.1
                    
NuGet\Install-Package XYS.DataFactory -Version 3.1.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="XYS.DataFactory" Version="3.1.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="XYS.DataFactory" Version="3.1.1" />
                    
Directory.Packages.props
<PackageReference Include="XYS.DataFactory" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add XYS.DataFactory --version 3.1.1
                    
#r "nuget: XYS.DataFactory, 3.1.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package XYS.DataFactory@3.1.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=XYS.DataFactory&version=3.1.1
                    
Install as a Cake Addin
#tool nuget:?package=XYS.DataFactory&version=3.1.1
                    
Install as a Cake Tool

XYS.DataFactory

基于 Dapper 的通用、异步、多目标数据库工具库。

特性

  • DbAgent 门面:Execute / ExecuteScalar / Query / QueryFirstOrDefault / QuerySingle / QuerySingleOrDefault / QueryMultiple真·多结果集)/ 存储过程。
  • 全部操作异步优先(支持 CancellationToken),另提供同步包装。
  • DbSession 显式事务单元:using 包裹自动回滚;Commit/Rollback 显式;同一 Session 内多操作复用连接与事务。
  • DbProviderRegistry 显式提供者注册,根治 .NET Core / .NET 5+ 上 DbProviderFactories.GetFactory 因无 machine.config 而失败的问题。
  • SqlCatalog 替代旧 SqlManager:按文件缓存 + 文件写入时间失效;未命中返回 null;IO/解析异常向上抛出,不再吞。
  • 失败一律抛 DbOperationException / DbConfigurationException,废除哨兵值(-1 / false / null / 空集合)。
  • 每操作用 ADO.NET 内置连接池取一根池化连接,天然支持高并发;不自建池。
  • 多目标:net8.0 / net462 / netcoreapp3.1 / netstandard2.1。
  • IDbParametersagent.Parameters()):provider 中立参数集合,AddLargeText/AddLargeBinary/AddDate 由方言特化为 CLOB/BLOB/MAX/Date,Oracle 下自动开 BindByName
  • RunOnCommand 逃生口 + DbAgentException(Message 不含 SQL 原文,原文在 Data["Sql"])+ 开发期参数-占位符校验(DbOptions.ValidateParameters)。

快速开始

using System.Data.SqlClient;
using XYS.DataFactory;

// 1. 应用启动时显式注册提供者(.NET Core/.NET 5+ 必需;net462 走 machine.config 可省略)
DbProviderRegistry.Register("System.Data.SqlClient", SqlClientFactory.Instance);

// 2. 从 xys.config.json 的 connectionStrings 节点构造(或用 new DbAgent(new DbOptions {...}))
using var db = DbAgent.FromConfig("hisConn");

// 3. 使用
var rows = await db.QueryAsync<Person>(
    "SELECT id, name FROM t_person WHERE age > @Age",
    new { Age = 30 });

int affected = await db.ExecuteAsync(
    "UPDATE t_person SET status='ACTIVE' WHERE id=@Id",
    new { Id = 42 });

// 真·多结果集
var pair = await db.QueryMultipleAsync(
    "SELECT COUNT(*) FROM t_person; SELECT name FROM t_person",
    async grid =>
    {
        long cnt = await grid.ReadFirstAsync<long>();
        var names = (await grid.ReadAsync<string>()).AsList();
        return (cnt, names);
    });

事务:DbSession

using var db = DbAgent.FromConfig("hisConn");
using (var s = await db.BeginSessionAsync())
{
    await s.ExecuteAsync("INSERT INTO t_order(no) VALUES(@No)", new { No = "20260717001" });
    await s.ExecuteAsync("UPDATE t_stock SET qty=qty-@Q WHERE id=@Id", new { Q = 1, Id = 100 });
    await s.CommitAsync();          // 必须显式 Commit;否则 Dispose 时回滚
}

未显式 Commit/Rollback 时,DbSession.DisposeRollback 并释放连接。

存储过程

用 Dapper 原生 DynamicParameters 承载输入/输出参数:

var p = new DynamicParameters();
p.Add("@id", 42);
p.Add("@out_name", dbType: DbType.String, direction: ParameterDirection.Output, size: 100);

await db.ExecuteProcedureAsync("sp_get_name", p);
string name = p.Get<string>("@out_name");

提供者注册

.NET Core / .NET 5+ / .NET 8 因不再有 machine.configDbProviderFactories.GetFactory("System.Data.SqlClient") 会失败。宿主必须在启动时显式注册:

// 常见提供者
DbProviderRegistry.Register("System.Data.SqlClient", SqlClientFactory.Instance);
DbProviderRegistry.Register("Microsoft.Data.SqlClient", Microsoft.Data.SqlClient.SqlClientFactory.Instance);
DbProviderRegistry.Register("Oracle.ManagedDataAccess.Client", Oracle.ManagedDataAccess.Client.OracleClientFactory.Instance);
DbProviderRegistry.Register("Microsoft.Data.Sqlite", SqliteFactory.Instance);

net462 上 DbProviderFactories 仍走 machine.config;未显式注册时自动回退。

错误处理

异常 场景
DbOperationException SQL 执行失败、结果映射失败、连接打开失败等运行时错误;InnerException 保留底层原始异常
DbConfigurationException 提供者名未注册、DbOptions.ConnStr 为空等配置错误
OperationCanceledException CancellationToken 取消;不被包装,直接冒泡

配置(xys.config.json)

"connectionStrings": {
  "hisConn": {
    "connectionString": "Data Source=...;Initial Catalog=...;User Id=...;Password=...",
    "providerName": "System.Data.SqlClient"
  }
}

DbAgent.FromConfig("hisConn")SystemInfo.GetConnStruct 读取。仓库中的 xys.config.json 不应写入明文凭据,仅在部署环境的实际配置文件中填写。

SqlCatalog

替代旧 SqlManager

var node = SqlCatalog.Default.GetNode("QueryPatient");            // 单条节点
string sql = SqlCatalog.Default.GetSql("QueryPatient");           // SQL 原文
string dyn = SqlCatalog.Default.GetSqlWithFilters(                 // 动态 where 拼接
    "QueryPatient",
    new[] { "PatId", "PatName" });

XML 配置仍放 {ApplicationBaseDirectory}/Config/sql.xml,结构与旧 SqlManager 兼容:

<root>
  <sql name="QueryPatient">
    <value>SELECT * FROM t_patient</value>
    <where field="PatId">PAT_ID=@PatId</where>
    <where field="PatName">PAT_NAME=@PatName</where>
  </sql>
</root>

按文件缓存,文件写入时间变化后下一次访问自动重载。Invalidate() 可强制刷新。

3.0.0 变更(不兼容点)

  • 旧存储过程反射插件体系(6 个 *.DBManager 提供者项目 + Assembly.LoadFrom)已移除。该路径在旧版本因类型分裂与反射参数不回读本就不可用;DBManager.ExecStoredProcedure / ExecSimpleStoredProcedure 现直接抛 NotSupportedException 指引到新 API。
  • DBFactory / DBManager / SqlManager / DBParameters / Clause 全部标记 [Obsolete],保留至下一个大版本;内部行为已修复但公共签名不变。修复项:
    • DBFactory 提供者解析走 DbProviderRegistry,修复 .NET Core 上原本不可用的问题。
    • DBManager.Executes 不再擅自回滚调用者拥有的事务,异常直接冒泡(旧实现擅自 Rollback 违反契约)。
    • SqlManager.GetInsertSql / GetUpdateSql 不再受 descendantFilter bug 影响。
    • DBParameters.AddString 的 dbType 由硬编码 0(AnsiString,中文对 NVarChar 有隐式转换/索引失效风险)改为 null,交由 Dapper 推断。
  • 双 csproj(旧式 XYS.DataFactory.Net462.csproj)已删除,避免同名程序集出现两种行为。

迁移指南

只读查询链(覆盖解决方案内 100% 现有调用):

// 旧
using (var factory = new DBFactory(connName))
{
    var dbManager = new DBManager(factory);
    dbManager.Conn.Open();
    var ps = new DBParameters();
    ps.AddDynamicParams(dict);
    var row = dbManager.QuerySingleOrDefault<Entity>(sql, ps);
}

// 新
using var db = DbAgent.FromConfig(connName);
var row = await db.QuerySingleOrDefaultAsync<Entity>(sql, dict);

架构

DbAgent  ──── 门面:Execute/Query 全套异步 + 同步包装 + 存储过程 + 事务入口
   │  每操作 using 池化连接(ADO.NET 自带池化)
   ▼
DbSession ── 显式事务单元:持一根连接与事务,暴露与 DbAgent 同形操作面
   │
   ▼
DbProviderRegistry ── 编译期强类型提供者注册,根治 .NET Core 上 GetFactory 断裂
   │
   ▼
DbProviderFactory / Dapper

Oracle / SqlServer 常见坑(3.1.0)

  1. 参数占位符:Oracle 用 :name,SqlClient 用 @name
  2. BindByName:走 agent.Parameters()RunOnCommand 时,Oracle 的 BindByName 由框架自动开启;直接传匿名对象走 Dapper 原生管道则不注入,Oracle 场景请优先用 agent.Parameters()
  3. CLOB / BLOB 写入:用 agent.Parameters().AddLargeText(...) / AddLargeBinary(...)不要DbType.String, size:-1(Oracle.ManagedDataAccess 的 size:-1 与 SqlClient 的 MAX 语义不同,会抛 ArgumentOutOfRangeException)。
  4. DateTime:Oracle DATE 列用 AddDate(内建 OracleDbType.Date);DateTime.MinValue 自动转 DBNull(规避 ORA-01841)。SqlServer 走 DateTime2
  5. 同名占位符:Oracle 场景即便逻辑同值,也应拆两个占位符(如 :CreatedTime / :ModifiedTime),保持 SQL 意图清晰。
  6. 异常消息DbAgentException.Message 不含 SQL 原文,可安全回前端;SQL 原文在 Exception.Data["Sql"]。需要在 Message 里带 SQL 时开 DbOptions.IncludeSqlInMessage(默认关)。
  7. 开发期校验:Dev 环境开 DbOptions.ValidateParameters,占位符缺参数会在执行前抛 MissingParameterException

大文本 / 日期写入示例

var ps = agent.Parameters()
    .Add("Id", id)
    .Add("Title", title)
    .AddLargeText("Content", htmlClob)   // Oracle CLOB / SqlServer NVARCHAR(MAX)
    .AddDate("CreatedTime", now)         // Oracle Date / SqlServer DateTime2
    .AddDate("ModifiedTime", now);
await agent.ExecuteAsync(insertSql, ps);

逃生口(provider 私有 API)

await agent.RunOnCommandAsync(sql, async (cmd, ct) =>
{
    var p = cmd.CreateParameter();
    p.ParameterName = "Content";
    p.Value = html;
    cmd.Parameters.Add(p);
    return await cmd.ExecuteNonQueryAsync(ct);
});

2.x → 3.1 参数迁移映射

旧(业务侧手写)
SqlMapper.IDynamicParameters 手构 OracleParameter{OracleDbType=Clob} agent.Parameters().AddLargeText(name, value)
new OracleParameter(n, OracleDbType.Date){Value=dt} agent.Parameters().AddDate(name, dt)
手动 ocmd.BindByName = true agent.Parameters() / RunOnCommand 自动开
DynamicParameters.Add(n, v, DbType.String, size:-1)(Oracle 会抛) agent.Parameters().AddLargeText(n, v)
异常 Message 拼 SQL 回前端 DbAgentException.Message(无 SQL);原文在 Data["Sql"]
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 is compatible. 
.NET Standard netstandard2.1 is compatible. 
.NET Framework net462 is compatible.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (15)

Showing the top 5 NuGet packages that depend on XYS.DataFactory:

Package Downloads
XYS.Lab.Report

Description

XYS.His.Common

Package Description

XYS.His.Hos

Package Description

XYS.FR.Net462

Description

XYS.FR.ZhiFang

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.1.1 108 7/24/2026
3.1.0 103 7/23/2026
3.0.0 105 7/22/2026
2.3.2 104 7/14/2026
2.3.1 103 7/14/2026
2.1.2.1 758 5/12/2024
2.1.1.3 446 12/14/2023
2.1.1.2 275 11/26/2023
2.1.1.1 367 5/15/2023
2.1.0.3 567 11/23/2022
2.1.0.1 953 5/10/2022
2.0.2.3 3,789 1/18/2022
2.0.2.2 2,016 12/21/2021
2.0.2.1 797 12/20/2021
2.0.1.1 654 12/20/2021
1.0.1.8 10,277 5/31/2021
1.0.1.7 1,089 5/28/2021
1.0.1.6 2,228 5/25/2021
1.0.1.5 1,258 5/10/2021
1.0.1.4 762 5/10/2021
Loading failed