XYS.DataFactory
3.1.1
dotnet add package XYS.DataFactory --version 3.1.1
NuGet\Install-Package XYS.DataFactory -Version 3.1.1
<PackageReference Include="XYS.DataFactory" Version="3.1.1" />
<PackageVersion Include="XYS.DataFactory" Version="3.1.1" />
<PackageReference Include="XYS.DataFactory" />
paket add XYS.DataFactory --version 3.1.1
#r "nuget: XYS.DataFactory, 3.1.1"
#:package XYS.DataFactory@3.1.1
#addin nuget:?package=XYS.DataFactory&version=3.1.1
#tool nuget:?package=XYS.DataFactory&version=3.1.1
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。
IDbParameters(agent.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.Dispose 会 Rollback 并释放连接。
存储过程
用 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.config,DbProviderFactories.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)
- 参数占位符:Oracle 用
:name,SqlClient 用@name。 - BindByName:走
agent.Parameters()或RunOnCommand时,Oracle 的BindByName由框架自动开启;直接传匿名对象走 Dapper 原生管道则不注入,Oracle 场景请优先用agent.Parameters()。 - CLOB / BLOB 写入:用
agent.Parameters().AddLargeText(...)/AddLargeBinary(...);不要传DbType.String, size:-1(Oracle.ManagedDataAccess 的size:-1与 SqlClient 的 MAX 语义不同,会抛ArgumentOutOfRangeException)。 - DateTime:Oracle DATE 列用
AddDate(内建OracleDbType.Date);DateTime.MinValue自动转DBNull(规避ORA-01841)。SqlServer 走DateTime2。 - 同名占位符:Oracle 场景即便逻辑同值,也应拆两个占位符(如
:CreatedTime/:ModifiedTime),保持 SQL 意图清晰。 - 异常消息:
DbAgentException.Message不含 SQL 原文,可安全回前端;SQL 原文在Exception.Data["Sql"]。需要在 Message 里带 SQL 时开DbOptions.IncludeSqlInMessage(默认关)。 - 开发期校验: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 | Versions 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. |
-
.NETCoreApp 3.1
- Dapper (>= 2.1.66)
- XYS.Utils.Log4Net (>= 2.5.0)
- XYS.Utils.Sys (>= 2.5.0)
-
.NETFramework 4.6.2
- Dapper (>= 2.1.66)
- XYS.Utils.Log4Net (>= 2.5.0)
- XYS.Utils.Sys (>= 2.5.0)
-
.NETStandard 2.1
- Dapper (>= 2.1.66)
- XYS.Utils.Log4Net (>= 2.5.0)
- XYS.Utils.Sys (>= 2.5.0)
-
net8.0
- Dapper (>= 2.1.66)
- XYS.Utils.Log4Net (>= 2.5.0)
- XYS.Utils.Sys (>= 2.5.0)
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 |