Liwendong.Frameworks.Data.DapperExtend 1.5.1

dotnet add package Liwendong.Frameworks.Data.DapperExtend --version 1.5.1
                    
NuGet\Install-Package Liwendong.Frameworks.Data.DapperExtend -Version 1.5.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="Liwendong.Frameworks.Data.DapperExtend" Version="1.5.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Liwendong.Frameworks.Data.DapperExtend" Version="1.5.1" />
                    
Directory.Packages.props
<PackageReference Include="Liwendong.Frameworks.Data.DapperExtend" />
                    
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 Liwendong.Frameworks.Data.DapperExtend --version 1.5.1
                    
#r "nuget: Liwendong.Frameworks.Data.DapperExtend, 1.5.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 Liwendong.Frameworks.Data.DapperExtend@1.5.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=Liwendong.Frameworks.Data.DapperExtend&version=1.5.1
                    
Install as a Cake Addin
#tool nuget:?package=Liwendong.Frameworks.Data.DapperExtend&version=1.5.1
                    
Install as a Cake Tool

Liwendong.Frameworks.Data.DapperExtend

Dapper 扩展:基于实体特性自动生成增删改查 SQL,并提供表达式条件、分页、事务与异步能力。

目标框架:net8.0;netcoreapp3.1;net451;net46;net47;net48

安装

dotnet add package Liwendong.Frameworks.Data.DapperExtend

快速开始

1. 定义实体

[DapperTable("Sys_User")]           // 不标注时默认使用类名,支持 "dbo.Users" 这种带架构的写法
public class User : IDapperEntityAutoRegister
{
    [DapperColumn(IsPrimaryKey = true, IsIdentity = true)]
    public int Id { get; set; }

    [DapperColumn("user_name")]      // 数据库栏目名与属性名不一致时使用
    public string UserName { get; set; }

    public int Age { get; set; }

    [DapperColumn(IsOnlyIgnoreUpdate = true)]
    public DateTime CreateTime { get; set; }

    [DapperColumn(IsIgnore = true)]  // 不参与任何 SQL
    public string ExtendData { get; set; }
}

DapperColumnAttribute 可用属性:

属性 说明
ColumnName 数据库栏目名
IsPrimaryKey 主键(用于 WHERE 条件)
IsIdentity 自增长列(不参与插入与更新)
IsIgnore 完全忽略
IsOnlyIgnoreInsert 仅忽略插入
IsOnlyIgnoreUpdate 仅忽略更新

2. 初始化

// 默认 SQL Server
var handler = new DapperHandler(connectionString);

注意(仅支持 SQL Server):内置增删改查/分页 SQL 模板均为 T-SQL 专属语法(SELECT TOP 1、SCOPE_IDENTITY()、ROW_NUMBER() 等), 只支持 SQL Server。构造函数虽可传入自定义连接工厂,但并不能让这些 CRUD 模板工作在 MySQL/SQLite/PostgreSQL 上, 仅适用于自行传入 SQL 的 Execute/GetList 等方法。

3. 增删改查

// 新增
handler.Insert(user);
long newId = handler.InsertReturnId(user);        // 返回自增长主键

// 按主键查询
var u1 = handler.GetEntityInfo(new User { Id = 1 });
var u2 = handler.GetEntityInfo<User>(new { Id = 1 });

// 按条件查询(全部参数化,无注入风险)
var u3 = handler.GetEntityInfo<User>(x => x.UserName == "张三" && x.Age > 18);

// 列表
var list = handler.GetList<User>(x => x.Age >= 18);
var all  = handler.GetAllList<User>();

// 更新
handler.Update(user);                            // 全字段更新(未赋值字段会被写成 NULL)
handler.UpdateIgnoreNull(user);                  // 只更新非 null 字段,推荐
handler.Update(user, x => new { x.Age });        // 只更新指定列
handler.Update(user, x => new { x.Age });        // 只更新指定列
handler.UpdateWhere(user, x => x.Age > 18);      // 按条件更新

// 删除
handler.Delete(user);                            // 按主键
handler.DeleteByKey<User>(new { Id = 1 });
handler.DeleteWhere<User>(x => x.Age < 18);      // 按条件删除

// 统计
int count = handler.Count<User>(x => x.Age >= 18);
bool exists = handler.Exists<User>(x => x.UserName == "张三");

分页

var page = handler.GetPageList<User>(1, 20, "Id DESC", x => x.Age >= 18);
// page.Items / page.TotalCount / page.TotalPages / page.HasNext

排序字段 orderBy 只接受「字段名 + ASC/DESC」,含其他字符会直接抛异常,避免拼接注入。

表达式条件支持范围

写法 生成 SQL
x => x.Age == 18 [Age]=@wp0
x => x.UserName != null [UserName] IS NOT NULL
x => (x.Age == 1 \|\| x.Age == 2) && x.Id > 0 (([Age]=@wp0 OR [Age]=@wp1) AND [Id]>@wp2)
x => !x.IsDel NOT ([IsDel]=@wp0)
x => x.UserName.Contains("张") [UserName] LIKE @wp0 ESCAPE '\'
x => x.UserName.StartsWith("张") [UserName] LIKE @wp0 ESCAPE '\'
x => ids.Contains(x.Id) [Id] IN (@wp0,@wp1,...)
  • 所有值一律走 Dapper 参数化,不做字符串拼接,不存在 SQL 注入。
  • AND/OR 自动补括号,不会出现优先级导致的语义反转。
  • 空集合的 Contains 会生成 (1=0),不会产生非法 SQL。
  • 不支持的表达式会抛 EasyErrorException,不会静默生成畸形 SQL。
  • x => !x.IsDel 会生成 ([IsDel]=0),不依赖数据库对 bit 的隐式布尔转换。

提示:UpdateIgnoreNull 只能跳过值为 null 的字段。bool、int、DateTime 等值类型永远不为 null, 若希望它们也能被跳过,请把属性声明为 bool?、int?、DateTime?。

事务

// 方式一:SQL 集合
var result = handler.ExecuteTransaction(new List<Tuple<string, object>>
{
    new Tuple<string, object>("UPDATE Sys_User SET Age=@Age WHERE Id=@Id", new { Age = 20, Id = 1 }),
    new Tuple<string, object>("DELETE FROM Sys_Log WHERE UserId=@UserId", new { UserId = 1 })
});
if (result.Item1 == false) { /* result.Item2 为错误信息 */ }

// 方式二:回调(支持事务内查询,异常向外抛出)
handler.ExecuteTransaction((db, trans) =>
{
    db.Execute("UPDATE ...", new { Id = 1 }, trans);
    db.Execute("DELETE ...", new { Id = 1 }, trans);
});

// 方式三:回调带回返回值
var id = handler.ExecuteTransaction((db, trans) =>
    db.ExecuteScalar<long>("INSERT ...; SELECT SCOPE_IDENTITY();", null, trans));

异步

所有主要方法都有对应的 Async 版本,支持 CancellationToken:

var user = await handler.GetEntityInfoAsync<User>(x => x.Id == 1, cancellationToken);
var list = await handler.GetListAsync<User>(x => x.Age >= 18);
int rows = await handler.ExecuteAsync("UPDATE Sys_User SET Age=@Age", new { Age = 20 });
long newId = await handler.InsertReturnIdAsync(user);

存储过程

var p = new DynamicParameters();
p.Add("UserId", 1);
p.Add("Total", dbType: DbType.Int32, direction: ParameterDirection.Output);

var list = handler.QueryStoredProcedure<User>("sp_GetUsers", p);
int total = p.Get<int>("Total");        // 读取输出参数

栏目名与属性名不一致时的映射

查询回来的数据要映射回实体,需要提前注册 TypeMap:

// 单个实体
DapperColumnMapper.SetMapper<User>();

// 批量注册所有实现 IDapperEntityAutoRegister 的实体
DapperColumnMapper.AllSetMapper();
// .NET Framework 项目 dll 不在根目录时
DapperColumnMapper.AllSetMapper(searchAllDrictory: true, appendDirectory: "bin");

建议在应用程序启动时执行一次即可。

版本历史

1.5.1 (2026-10-17)

  • 修复:更新列默认排除主键,主键不再被写进 SET 子句(UpdateColumns/UpdateSetSQL)
  • 修复:BuildUpdateIgnoreNull 主键值为 null 时 WHERE 引用缺失参数报错,改为直接抛 EasyErrorException;补充"值类型属性永远非 null"的说明
  • 修复:string.Contains(s, StringComparison) 两参重载被误判为 IN 查询,先判定调用对象为 string 走 LIKE/Contains 字符串语义
  • 修复:嵌套成员 x.Child.Name 被静默映射成实体同名栏目生成错误条件,改为明确抛"不支持的表达式"
  • 修复:分页 (pageIndex-1)*pageSize int 溢出,改 long 计算;GetPageList 统计总数复用同一 where 构建结果,避免与分页条件不一致
  • 修复:列名映射比较改 StringComparison.OrdinalIgnoreCase;TrimQuote 按首尾成对剥括号,保留 ]] 转义不再破坏含 ] 的标识符
  • 修复:无可插入/更新栏目的只读实体在 Build 阶段抛错导致无法查询,改为仅在执行 Insert/Update 时报错
  • 修复:using System.Data.SqlClient 与 Microsoft.Data.SqlClient 对齐条件编译,避免误导
  • 修复:SQL 模板为 T-SQL 专属但文档声称支持 MySQL 等,修正 XML/README 文档为"仅 SQL Server"
  • 优化:删除 DapperColumnAttribute 注释掉的重复构造函数死代码
  • 优化:ExecuteTransaction(List<Tuple>) 吞异常行为保留,XML 注释明确"检查 Item1"并推荐回调式重载;InsertBatch 标注逐条执行(N+1),大批量请用 SqlBulkCopy

1.5.0 (2026-10-15)

  • 新增:net8.0 目标框架(Dapper 2.1.66 + Microsoft.Data.SqlClient 5.2.3)
  • 新增:net47 目标框架(Dapper 2.1.66)

1.4.0 (2026-10-10)

  • 修复:Delete 两个重载因 SQL_DELETE 占位符写成 {2} 却只传 2 个参数,必然抛 FormatException,删除功能完全不可用
  • 修复:Where 条件由字符串拼接改为 Dapper 参数化,消除 SQL 注入风险
  • 修复:AND/OR 组合未加括号,导致 (a || b) && c 语义反转、误删误查数据
  • 修复:一元 Not 表达式被丢弃,x => !x.IsDel 生成非法 SQL
  • 修复:bool/Guid/DateTime/闭包字符串等值生成非法 SQL;null 值不再触发空引用异常
  • 修复:Contains/StartsWith/IN 等方法调用静默返回空串,拼出畸形 SQL,现显式抛异常
  • 修复:DapperColumnAttribute/DapperTableAttribute 的 AllowMultiple = true 与单取特性矛盾,重复标注会抛 AmbiguousMatchException
  • 修复:ExecuteTransaction 中 Stopwatch 死代码与重复的连接关闭;异常信息不再返回完整堆栈
  • 优化:引入 DapperEntityMeta 元数据缓存,消除每次 CRUD 的重复反射
  • 优化:表名统一转义,支持 dbo.Users 带架构写法
  • 优化:GetEntityInfo 两个重载的重复代码合并
  • 新增:GetList(表达式)、GetAllList、Count、Exists、GetPageList 分页
  • 新增:InsertReturnId、InsertBatch、UpdateIgnoreNull、UpdateWhere、DeleteWhere、DeleteByKey
  • 新增:ExecuteScalar、QueryStoredProcedure、QueryFirstStoredProcedure
  • 新增:全链路 Async 方法与 CancellationToken 支持
  • 新增:ExecuteTransaction 支持 IsolationLevel 与回调式事务
  • 新增:连接工厂注入(注意:内置 SQL 模板为 T-SQL 专属,仅支持 SQL Server,连接工厂只适用于自行传入 SQL 的方法)
  • 新增:net48 目标框架(使用 Dapper 2.1.66)
  • 新增:README.md 与 PackageTags 包元数据
  • 新增:每个公开 API 的完整 XML 注释(暂未生成 XML 文档文件,因其会连带开启 Liwendong.Utility 的文档生成并引入大量既有注释告警,建议单独处理)

1.3.0

  • 历史版本
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.1 is compatible. 
.NET Framework net451 is compatible.  net452 was computed.  net46 is compatible.  net461 was computed.  net462 was computed.  net463 was computed.  net47 is compatible.  net471 was computed.  net472 was computed.  net48 is compatible.  net481 was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.5.1 82 10/20/2026
1.2.0 224 8/23/2025
1.1.0 213 7/29/2025
1.0.0 571 6/18/2021