Dapper.Lite
一款Dapper扩展,单表查询和SQL拼接查询条件支持Lambda表达式。支持Oracle、MSSQL、MySQL、PostgreSQL、SQLite、Access、ClickHouse等数据库。如有问题加QQ群:497956447。
Install / Use
/learn @0611163/Dapper.LiteREADME
Dapper.Lite
简介
一款Dapper扩展,同时支持SQL拼接和简单的Lambda表达式。支持Oracle、MSSQL、MySQL、PostgreSQL、SQLite、Access等数据库。
经典示例
DateTime? startTime = null;
var session = DapperLiteFactory.GetSession();
session.OnExecuting = (s, p) => Console.WriteLine(s); //打印SQL
List<SysUser> list = session.Sql(@"
select * from sys_user t where t.id <= @Id", new { Id = 20 })
.Append(@" and t.create_userid = @CreateUserId
and t.password like @Password
and t.id in @Ids",
new
{
CreateUserId = "1",
Password = "%345%",
Ids = session.ForList(new List<int> { 1, 2, 9, 10, 11 })
})
.AppendIf(startTime.HasValue, " and t.create_time >= @StartTime ", new { StartTime = startTime })
.Append(" and t.create_time <= @EndTime ", new { EndTime = new DateTime(2022, 8, 1) })
.QueryList<SysUser>();
long id = session.Sql("select id from sys_user where id=@Id", new { Id = 1 })
.QuerySingle<long>();
Assert.IsTrue(id == 1);
foreach (SysUser item in list)
{
Console.WriteLine(ModelToStringUtil.ToString(item));
}
Assert.IsTrue(list.Count > 0);
经典示例2
var session = DapperLiteFactory.GetSession();
List<BsOrder> list = session
.Sql<BsOrder>(@"
select o.*, u.user_name as OrderUserName, u.real_name as OrderUserRealName
from bs_order o
left join sys_user u on u.id=o.order_userid")
.Where(o => o.Status == 0
&& o.Remark.Contains("订单")
&& o.OrderTime >= new DateTime(2010, 1, 1)
&& o.OrderTime < DateTime.Now.Date.AddDays(1))
.Where<SysUser>(u => new long[] { 8, 9, 10 }.Contains(u.Id))
.Append("order by o.order_time desc, o.id asc")
.ToList();
特点
- 支持Oracle、SQL Server、MySQL、PostgreSQL、SQLite五种数据库;另外只要ADO.NET支持的数据库,都可以很方便地通过实现IProvider接口支持,仅需写150行左右的代码
- 有配套的Model生成器
- 数据插入、更新、批量插入、批量更新,支持实体类、实体类集合,无需拼SQL;删除操作支持根据主键或查询条件删除;增删改支持联合主键
- 查询以原生SQL为主,查询Where条件可以拼接Lambda表达式
- 支持参数化查询,统一不同数据库的参数化查询SQL
- 支持连接多个数据源
- 支持手动分表
- 单表查询支持Lambda表达式
优点
- 比较简单,学习成本低
- 查询以原生SQL为主,Lambda表达式辅助
- 代码量仅4000多行,更容易修改和掌控代码质量
缺点
- 对Lambda表达式的支持比较弱
- 复杂查询不支持Lambda表达式(连表查询、子查询、分组统计查询、嵌套查询等不支持Lambda表达式写法)
建议
- 单表查询可以使用Lambda表达式
- 复杂查询建议使用原生SQL
- 如果出现不支持的Lambda表达式写法,请使用原生SQL替代
开发环境
- VS2022
- 目标框架:net461;netstandard2.0;net5.0
- 测试工程使用.NET Framework 4.5.2
配套Model生成器地址:
https://gitee.com/s0611163/ModelGenerator
支持 ClickHouse 数据库
https://gitee.com/s0611163/ClickHouseTest
这是一个示例,只要ADO.NET支持的数据库,您都可以通过实现IProvider接口尝试支持
.NET 6 环境下测试
https://gitee.com/s0611163/LiteSqlTest
作者邮箱
651029594@qq.com
使用步骤
- 安装Dapper.Lite
Install-Package Dapper.Lite -Version 1.8.28
- 安装对应的数据库引擎
Install-Package MySql.Data -Version 6.9.12
- 实现对应的数据库Provider
注意:各实现方法一定要加上override关键字以重写基类的方法
using Dapper.Lite;
using MySql.Data.MySqlClient;
using System.Data.Common;
namespace DAL
{
public class MySQLProvider : MySQLProviderBase, IDbProvider
{
#region 创建 DbConnection
public override DbConnection CreateConnection(string connectionString)
{
return new MySqlConnection(connectionString);
}
#endregion
#region 生成 DbParameter
public override DbParameter GetDbParameter(string name, object value)
{
return new MySqlParameter(name, value);
}
#endregion
}
}
- 定义DapperLiteFactory类
using Dapper.Lite;
using System.Configuration;
using System.Threading.Tasks;
namespace DAL
{
public class DapperLiteFactory
{
#region 变量
private static IDapperLite _dapperLite = new DapperLite(ConfigurationManager.ConnectionStrings["DefaultConnection"].ToString(), new MySQLProvider());
public static IDapperLite Client => _dapperLite;
#endregion
#region 获取 IDbSession
/// <summary>
/// 获取 IDbSession
/// </summary>
/// <param name="splitTableMapping">分表映射</param>
public static IDbSession GetSession(SplitTableMapping splitTableMapping = null)
{
return _dapperLite.GetSession(splitTableMapping);
}
#endregion
#region 获取 IDbSession (异步)
/// <summary>
/// 获取 IDbSession (异步)
/// </summary>
/// <param name="splitTableMapping">分表映射</param>
public static async Task<IDbSession> GetSessionAsync(SplitTableMapping splitTableMapping = null)
{
return await _dapperLite.GetSessionAsync(splitTableMapping);
}
#endregion
}
}
- 依赖注入
var builder = WebApplication.CreateBuilder(args);
var db = new DapperLite(builder.Configuration.GetConnectionString("DefaultConnection"), new MySQLProvider());
var secondDB = new DapperLite<SecondDbFlag>(builder.Configuration.GetConnectionString("SecondConnection"), new MySQLProvider());
// Add services to the container.
// 注册数据库IDapperLite
builder.Services.AddSingleton<IDapperLite>(db);
// 注册第二个数据库IDapperLite
builder.Services.AddSingleton<IDapperLite<SecondDbFlag>>(secondDB);
// 注册数据库DbSession
builder.Services.AddScoped<IDbSession>(serviceProvider =>
{
return serviceProvider.GetService<IDapperLite>().GetSession();
});
// 注册第二个数据库DbSession
builder.Services.AddScoped<IDbSession<SecondDbFlag>>(serviceProvider =>
{
return serviceProvider.GetService<IDapperLite<SecondDbFlag>>().GetSession();
});
/// <summary>
/// 第二个数据库标识
/// </summary>
public class SecondDbFlag { }
配套Model生成器
使用Model生成器生成实体类
- 实体类放在Models文件夹中
- 扩展实体类放在ExtModels文件夹中
- 实体类和扩展实体类使用partial修饰,实际上是一个类,放在不同的文件中
- 如果需要添加自定义属性,请修改ExtModels,不要修改Models
实体类示例
using System;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
/// <summary>
/// 订单表
/// </summary>
[Serializable]
[Table("bs_order")]
public partial class BsOrder
{
/// <summary>
/// 主键
/// </summary>
[Key]
public string Id { get; set; }
/// <summary>
/// 订单时间
/// </summary>
[Column("order_time")]
public DateTime OrderTime { get; set; }
/// <summary>
/// 订单金额
/// </summary>
public decimal? Amount { get; set; }
/// <summary>
/// 下单用户
/// </summary>
[Column("order_userid")]
public long OrderUserid { get; set; }
/// <summary>
/// 订单状态(0草稿 1已下单 2已付款 3已发货 4完成)
/// </summary>
public int Status { get; set; }
/// <summary>
/// 备注
/// </summary>
public string Remark { get; set; }
/// <summary>
/// 创建者ID
/// </summary>
[Column("create_userid")]
public string CreateUserid { get; set; }
/// <summary>
/// 创建时间
/// </summary>
[Column("create_time")]
public DateTime CreateTime { get; set; }
/// <summary>
/// 更新者ID
/// </summary>
[Column("update_userid")]
public string UpdateUserid { get; set; }
/// <summary>
/// 更新时间
/// </summary>
[Column("update_time")]
public DateTime? UpdateTime { get; set; }
}
修改扩展实体类
- 修改扩展实体类,添加自定义属性
- 下面的扩展实体类中,查询时OrderUserRealName会被自动填充,查询SQL:select t.*, u.real_name as OrderUserRealName from ......
- DetailList不会被自动填充,需要手动查询
扩展实体类示例
/// <summary>
/// 订单表
/// </summary>
public partial class BsOrder
{
/// <summary>
/// 订单明细集合
/// </summary>
[NotMapped]
public List<BsOrderDetail> DetailList { get; set; }
/// <summary>
/// 下单用户姓名
/// </summary>
[NotMapped]
public string OrderUserRealName { get; set; }
/// <summary>
/// 下单用户名
/// </summary>
[NotMapped]
public string OrderUserName { get; set; }
}
增删改查示例
添加
public void Insert(SysUser info)
{
var session = DapperLiteFactory.GetSession();
session.Insert(info);
}
添加并返回ID
public void Insert(SysUser info)
{
var session = DapperLiteFactory.GetSession();
long id = session.InsertReturnId(info, "select @@IDENTITY");
}
批量添加
public void Insert(List<SysUser> list)
{
var session = DapperLiteFactory.GetSession();
session.Insert(list);
}
修改
public void Update(SysUser info)
{
var session = DapperLiteFactory.GetSession();
session.Update(info);
}
批量修改
public void Update(List<SysUser> list)
{
var session = DapperLiteFactory.GetSession();
session.Update(list);
}
修改时只更新数据有变化的字段
var session = DapperLiteFactory.GetSession();
session.AttachOld(user); //附加更新前的旧数据,只更新数据发生变化的字段,提升更新性能
user.UpdateUserid = "1";
user.Remark = "测试修改用户" + _rnd.Next(1, 100);
user.UpdateTime = DateTime.Now;
session.Update(user);
var session = DapperLiteFactory.GetSession();
session.AttachOld(userList); //附加更新前的旧数据,只更新数据发生变化的字段,提升更新性能
foreach (SysUser user in userList)
{
user.Remark = "测试修改用户" + _rnd.Next(1, 10000);
user.UpdateUserid = "1";
user.UpdateTime = DateTime.Now;
}
session.Update(userList);
删除
public void Delete(string id)
{
var session = DapperLiteFactory.GetSession();
session.DeleteById<SysUser>(id);
}
条件删除
var session = DapperLiteFactory.GetSession();
session.Sql("id>@Id", 20).Delete<SysUser>();
var session = DapperLiteFactory.GetSession();
session.Queryable<SysUser>().Where(t => t.Id > 20).Delete();
查询单个记录
public SysUser Get(string id)
{
var session = DapperLiteFactory.GetSession();
return session.QueryById<SysUser>(id);
}
var session = DapperLiteFactory.GetSession();
SysUser user = session.Query<SysUser>("select * from sys_user");
简单查询
var session = DapperLiteFactory.GetSession();
string sql = "select * from CARINFO_MERGE";
List<CarinfoMerge> result = session.QueryList<CarinfoMerge>(sql);
条件查询
public List<BsOrder> GetList(int? status, string remark, DateTime? startTime, DateTime? endTime)
{
