DapperDal - 简单易用的微 ORM 类库,数据访问层基类
Introduction
基于 Dapper
、Dapper-Extensions
构建的微型 ORM 类库,提供一个包含增、删、改、查等常用方法的数据访问层基类,支持用 Lambda
表达式书写查询和更新条件。
Features
- 零配置,开箱即用。
- 数据库表、实体类型自动映射,主键自动映射。实体类上无需定义 Attribute。
- 灵活易用的增、删、改、查、分页查询等常用重载方法,单表操作无需编写任何 SQL 语句。
- 查询和更新条件支持
Lambda
表达式组合,自动生成安全参数化的 SQL 语句。 - 提供 SQL 语句、存储过程执行方法,返回结果集自动模型映射,比 DataSet 效率高。
- 支持部分字段更新,无变化字段不更新。
- 数据库表字段变化时重新生成实体类即可,数据访问层无需重新生成。
- 基类定义了 IDbConnection 属性,所有
Dapper
、Dapper-Extensions
方法都能使用。 - 完善的单元测试。
- 命名约定:实体类名和数据库表名应匹配,实体属性名与表字段名应匹配。主键字段名应以
Id
命名或结尾 - 限制:多表联合查询还是需要编写 SQL 语句或者存储过程。
Installation
https://www.nuget.org/packages/DapperDal
PM> Install-Package DapperDal
API Document
https://arbing.github.io/DapperDal
Examples
定义实体类 PersonEntity
/// <summary>
/// 人员信息表实体类
/// </summary>
public class PersonEntity
{
public long PersonId { get; set; }
public string PersonName { get; set; }
public int CarId { get; set; }
public DateTime CreateTime { get; set; }
public DateTime UpdateTime { get; set; }
public short IsActive { get; set; }
}
数据访问层定义DAL类 PersonDal,继承自 DalBase
单条插入 多条批量插入 主键获取 条件获取 判断实体是否存在 更新实体 更新指定实体指定属性 根据指定更新条件更新实体指定属性 删除实体 列表查询 生成的 SQL 获取总条数 生成的 SQL 列表分页查询 生成的 SQL 执行查询语句 执行查询存储过程 执行多结果集查询语句 执行多结果集查询存储过程 执行语句 执行存储过程 执行带返回参数的存储过程 执行带返回参数的查询存储过程 其他常用方法 常见应用 Apache License 2.0/// <summary>
/// 人员信息表数据访问类
/// </summary>
public class PersonDal : DalBase<PersonEntity, long>
{
public PersonDal() : base(ConnectionNames.Default)
{
}
...
}
var personDal = new PersonDal();
PersonEntity p = new PersonEntity { PersonName = "Foo", CreateTime = DateTime.Now, UpdateTime = DateTime.Now };
long id = personDal.Insert(p);
var personDal = new PersonDal();
PersonEntity p1 = new PersonEntity { PersonName = "Foo", CreateTime = DateTime.Now, UpdateTime = DateTime.Now };
PersonEntity p2 = new PersonEntity { PersonName = "Bar", CreateTime = DateTime.Now, UpdateTime = DateTime.Now };
PersonEntity p3 = new PersonEntity { PersonName = "Baz", CreateTime = DateTime.Now, UpdateTime = DateTime.Now };
personDal.Insert(new[] { p1, p2, p3 });
var personDal = new PersonDal();
long personId = 1;
PersonEntity person = personDal.Get(id);
var personDal = new PersonDal();
PersonEntity person = personDal.GetFirst(p => p.PersonId = 1);
PersonEntity person = personDal.GetFirst(p => p.IsActive != 1);
PersonEntity person = personDal.GetFirst(p => UpdateTime >= DateTime.Today);
PersonEntity person = personDal.GetFirst(p => p.PersonId = 1 && p.IsActive == 1);
PersonEntity person = personDal.GetFirst(p => p.PersonId = 1 || p.PersonName = "Foo");
PersonEntity person = personDal.GetFirst(p => p.IsActive == 1 && (p.PersonName == "Foo" || p.CarId == 3));
PersonEntity person = personDal.GetFirst(p => p.PersonName.Equals("Foo"));
PersonEntity person = personDal.GetFirst(p => p.PersonName.Contains("a"));
PersonEntity person = personDal.GetFirst(p => p.PersonName.StartsWith("Ba"));
PersonEntity person = personDal.GetFirst(p => p.PersonName.EndsWith("az"));
var carIds = new[] { p2.CarId, 3, 2};
PersonEntity person = personDal.GetFirst(p => carIds.Contains(p.CarId));
var personDal = new PersonDal();
bool isExsit = personDal.Exsit(id: 1);
bool isExsit = personDal.Exsit(p => p.PersonId = 1);
var p2 = personDal.Get(id);
p2.IsActive = 1;
p2.PersonName = "Baz";
var result = personDal.Update(p2);
var p2 = personDal.Get(id);
p2.PersonName = "Baz";
p2.CarId = 2;
p2.IsActive = 1;
bool result = personDal.Update(p2, new[] { "personName", "CarId", "CarName" });
bool result = personDal.Update(p2, new { personName = "Baz", CarId = 2 });
bool result = personDal.Update(p2.PersonId, new { personName = "Baz", CarId = 2 });
var personName = p2.PersonName;
bool result = personDal.Update(new { p2.PersonId, personName, p2.CarId, CarName = "CarName" });
var personName = p2.PersonName;
bool result = personDal.Update(new { personName, p2.CarId, CarName = "CarName" }, p => p.PersonId == p2.PersonId);
PersonEntity p2 = personDal.Get(id);
bool result = personDal.Delete(p2);
bool result = personDal.Delete(p2.PersonId);
bool result = personDal.Delete(p => p.PersonName == "Bar");
IEnumerable<PersonEntity> persons = personDal.GetList().ToList();
IEnumerable<PersonEntity> persons = personDal.GetList(SortDirection.Descending, p => p.CarId);
IEnumerable<PersonEntity> persons = personDal.GetList(p.IsActive == 1 && p.PersonName == "c");
var predicate = PredicateBuilder.True<PersonEntity>();
predicate = predicate.And(p => p.IsActive == 1);
predicate = predicate.And(p => p.PersonName == "c");
IEnumerable<PersonEntity> persons = personDal.GetList(predicate);
var sort = new List<Sort>() { new Sort { PropertyName = "CarId", Ascending = false } };
IEnumerable<PersonEntity> persons = personDal.GetList(p => p.IsActive == 1, sort).ToList();
IEnumerable<PersonEntity> persons = personDal.GetList(p => p.IsActive == 1, SortDirection.Descending, p => p.CarId).ToList();
SELECT [Person].[PersonId], [Person].[PersonName], [Person].[CarId], [Person].[CreateTime], [Person].[UpdateTime], [Person].[IsActive]
FROM [Person] WITH (NOLOCK)
WHERE ([Person].[IsActive] = @IsActive_0)
ORDER BY [Person].[CarId] DESC
int count = personDal.Count(p => p.IsActive == 1)
SELECT COUNT(*) AS [Total] FROM [Person] WITH (NOLOCK)
WHERE ([Person].[IsActive] = @IsActive_0)
IEnumerable<PersonEntity> persons = personDal.GetListPaged(p => p.IsActive == 1, new { CarId = SortDirection.Descending }, pageNumber: 1, itemsPerPage: 20).ToList()
SELECT TOP(20) [_proj].[PersonId], [_proj].[PersonName], [_proj].[CarId], [_proj].[CreateTime], [_proj].[UpdateTime], [_proj].[IsActive]
FROM (
SELECT ROW_NUMBER() OVER(ORDER BY [Person].[CarId] DESC) AS [_row_number],
[Person].[PersonId], [Person].[PersonName], [Person].[CarId], [Person].[CreateTime], [Person].[UpdateTime], [Person].[IsActive]
FROM [Person] WITH (NOLOCK)
WHERE ([Person].[IsActive] = @IsActive_0)) [_proj]
WHERE [_proj].[_row_number] >= @_pageStartRow
ORDER BY [_proj].[_row_number]
IEnumerable<PersonModel> list = personDal.Query<PersonModel>(
"select PersonName as Name, CarId from Person where CarId = @CarId", new { CarId = 3 });
IEnumerable<PersonModel> list = personDal.Query<PersonModel>(
"dbo.P_GetPersonModelsByCarId",
new { CarId = 3 }, System.Data.CommandType.StoredProcedure);
Tuple<IEnumerable<PersonEntity>, IEnumerable<PersonModel>> tuple = personDal.QueryMultiple<PersonEntity, PersonModel>(
"select * from Person where CarId = @CarId;select PersonName AS [Name], CarId from Person where CarId = @CarId",
new { CarId = 3 });
Tuple<IEnumerable<PersonEntity>, IEnumerable<PersonModel>> tuple = personDal.QueryMultiple<PersonEntity, PersonModel>(
"P_GetPersonMultipleModelsByCarId", new { CarId = 3 }, System.Data.CommandType.StoredProcedure);
int affected = personDal.Execute("update Person set IsActive = 1 where CarId = @CarId", new { CarId = 3 });
int affected = personDal.Execute("P_SetPersonsByCarId", new { CarId = 3 }, System.Data.CommandType.StoredProcedure);
var parameters = new DynamicParameters(new { CarId = 3 });
parameters.Add("TotalCount", dbType: System.Data.DbType.Int32, direction: System.Data.ParameterDirection.Output);
int affected = personDal.Execute("P_SetPersonsByCarId_OutputCount", parameters, System.Data.CommandType.StoredProcedure);
int totalCount = parameters.Get<int>("TotalCount");
var parameters = new DynamicParameters(new { CarId = 3 });
parameters.Add("TotalCount", dbType: System.Data.DbType.Int32, direction: System.Data.ParameterDirection.Output);
IEnumerable<PersonModel> list = personDal.Query<PersonModel>(
"dbo.P_GetPersonModelsByCarId_OutputCount",
parameters, System.Data.CommandType.StoredProcedure);
int totalCount = parameters.Get<int>("TotalCount");
打开新的 IDbConnection
OpenConnection
执行SQL语句,返回第一行第一列数据
ExecuteScalar
获取前N条
GetTop
逻辑删除
SoftDelete
逻辑删除或激活
SwitchActive
/// <summary>
/// 请求分页数据时的参数基类
/// </summary>
public class PagedParam
{
/// <summary>
/// 初始化
/// </summary>
public PagedParam()
{
PageIndex = 1;
PageSize = 10;
}
/// <summary>
/// 当前页索引
/// </summary>
public int PageIndex { get; set; }
/// <summary>
/// 每页显示的记录数
/// </summary>
public int PageSize { get; set; }
/// <summary>
/// 要分页的数据总数
/// </summary>
public int RecordCount { get; set; }
}
/// <summary>
/// 获取人员分页列表的查询参数
/// </summary>
public class GetPersonPagedListParam : PagedParam
{
public string PersonName { get; set; }
public int CarId { get; set; }
/// <summary>
/// 创建起始时间
/// </summary>
public DateTime? BeginCreateTime { get; set; }
/// <summary>
/// 创建结束时间
/// </summary>
public DateTime? EndCreateTime { get; set; }
}
/// <summary>
/// 获取人员分页列表的返回实体
/// </summary>
public class GetPersonPagedListOutputDto // : PersonEntity
{
/// 人员信息
/// 其他信息
}
/// <summary>
/// 人员信息表数据访问类
/// </summary>
public class PersonDal : DalBase<PersonEntity, long>
{
public PersonDal() : base(ConnectionNames.Default)
{
}
/// <summary>
/// 获取人员分页列表
/// </summary>
/// <param name="param">查询参数</param>
/// <returns>人员分页列表</returns>
public PagingList<GetPersonPagedListOutputDto> GetPersonPagedList(GetPersonPagedListParam param)
{
var parameters = new DynamicParameters(param).Output(param, p => p.RecordCount);
var list = Query<GetPersonPagedListOutputDto>(
"p_GetPersonPagedList",
parameters,
commandType: CommandType.StoredProcedure)
.ToList();
return PagingList.Create(list, param.RecordCount);
}
}
Release Notes
1.5.19
SoftDelete
、SwitchActive
默认更新字段 UpdateTime = DateTime.Now
1.5.18
QueryDataSet
1.5.16
Dapper-Extensions
到 DapperDal
,然后移除 Dapper-Extensions
1.5.15
QueryFirstOrDefault
,可以使用 QueryFirst
替换OpenConnection
、Execute
、Query
, 支持传入其他 DB 连接串1.5.14
SwitchActive
GetFirstOrDefault
,可以使用 GetFirst
替换Update
、Delete
SoftDeleteProps
迁移到 DapperDal
中,新添加配置项 SoftActiveProps
1.5.13
1.5.12
Exsit
、Count
方法1.5.11
Exsit
1.5.10
SoftDeleteById
1.5.9
GetFirstOrDefault
、QueryFirstOrDefault
、QueryFirst
1.5.8
Execute
、ExecuteScalar
1.5.7
GetFirst
、GetTop
1.5.6
WITH (NOLOCK)
1.5.5
SoftDelete
1.5.4
QueryBuilder
替换 ExpressionVisitor
实现,以支持多个查询条件(来自ryanwatson/Dapper.Extensions.Linq)1.5.3
Query
方法1.5.2
Update
方法(来自vilix13/Dapper-Extensions)lambda
表达式作条件的 Update
方法1.5.1
Abp.Dapper
,为 Dapper-Extensions
添加 lambda
表达式功能(来自Abp.Dapper)License