# DapperDal
**Repository Path**: arbing/DapperDal
## Basic Information
- **Project Name**: DapperDal
- **Description**: 基于 Dapper、Dapper-Extensions 构建的微型 ORM 类库,提供一个包含增、删、改、查等常用方法的数据访问层基类,支持用 Lambda 表达式书写查询和更新条件
- **Primary Language**: C#
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 5
- **Forks**: 3
- **Created**: 2017-08-29
- **Last Updated**: 2023-10-23
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# DapperDal - 简单易用的微 ORM 类库,数据访问层基类
[](https://www.nuget.org/packages/DapperDal/)
[](https://ci.appveyor.com/project/arbing/dapperdal)
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
```
///
/// 人员信息表实体类
///
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
```
///
/// 人员信息表数据访问类
///
public class PersonDal : DalBase
{
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 persons = personDal.GetList().ToList();
IEnumerable persons = personDal.GetList(SortDirection.Descending, p => p.CarId);
IEnumerable persons = personDal.GetList(p.IsActive == 1 && p.PersonName == "c");
var predicate = PredicateBuilder.True();
predicate = predicate.And(p => p.IsActive == 1);
predicate = predicate.And(p => p.PersonName == "c");
IEnumerable persons = personDal.GetList(predicate);
var sort = new List() { new Sort { PropertyName = "CarId", Ascending = false } };
IEnumerable persons = personDal.GetList(p => p.IsActive == 1, sort).ToList();
IEnumerable persons = personDal.GetList(p => p.IsActive == 1, SortDirection.Descending, p => p.CarId).ToList();
```
生成的 SQL
```
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)
```
生成的 SQL
```
SELECT COUNT(*) AS [Total] FROM [Person] WITH (NOLOCK)
WHERE ([Person].[IsActive] = @IsActive_0)
```
列表分页查询
```
IEnumerable persons = personDal.GetListPaged(p => p.IsActive == 1, new { CarId = SortDirection.Descending }, pageNumber: 1, itemsPerPage: 20).ToList()
```
生成的 SQL
```
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 list = personDal.Query(
"select PersonName as Name, CarId from Person where CarId = @CarId", new { CarId = 3 });
```
执行查询存储过程
```
IEnumerable list = personDal.Query(
"dbo.P_GetPersonModelsByCarId",
new { CarId = 3 }, System.Data.CommandType.StoredProcedure);
```
执行多结果集查询语句
```
Tuple, IEnumerable> tuple = personDal.QueryMultiple(
"select * from Person where CarId = @CarId;select PersonName AS [Name], CarId from Person where CarId = @CarId",
new { CarId = 3 });
```
执行多结果集查询存储过程
```
Tuple, IEnumerable> tuple = personDal.QueryMultiple(
"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("TotalCount");
```
执行带返回参数的查询存储过程
```
var parameters = new DynamicParameters(new { CarId = 3 });
parameters.Add("TotalCount", dbType: System.Data.DbType.Int32, direction: System.Data.ParameterDirection.Output);
IEnumerable list = personDal.Query(
"dbo.P_GetPersonModelsByCarId_OutputCount",
parameters, System.Data.CommandType.StoredProcedure);
int totalCount = parameters.Get("TotalCount");
```
其他常用方法
```
打开新的 IDbConnection
OpenConnection
执行SQL语句,返回第一行第一列数据
ExecuteScalar
获取前N条
GetTop
逻辑删除
SoftDelete
逻辑删除或激活
SwitchActive
```
常见应用
```
///
/// 请求分页数据时的参数基类
///
public class PagedParam
{
///
/// 初始化
///
public PagedParam()
{
PageIndex = 1;
PageSize = 10;
}
///
/// 当前页索引
///
public int PageIndex { get; set; }
///
/// 每页显示的记录数
///
public int PageSize { get; set; }
///
/// 要分页的数据总数
///
public int RecordCount { get; set; }
}
///
/// 获取人员分页列表的查询参数
///
public class GetPersonPagedListParam : PagedParam
{
public string PersonName { get; set; }
public int CarId { get; set; }
///
/// 创建起始时间
///
public DateTime? BeginCreateTime { get; set; }
///
/// 创建结束时间
///
public DateTime? EndCreateTime { get; set; }
}
///
/// 获取人员分页列表的返回实体
///
public class GetPersonPagedListOutputDto // : PersonEntity
{
/// 人员信息
/// 其他信息
}
///
/// 人员信息表数据访问类
///
public class PersonDal : DalBase
{
public PersonDal() : base(ConnectionNames.Default)
{
}
///
/// 获取人员分页列表
///
/// 查询参数
/// 人员分页列表
public PagingList GetPersonPagedList(GetPersonPagedListParam param)
{
var parameters = new DynamicParameters(param).Output(param, p => p.RecordCount);
var list = Query(
"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
* 添加返回 DataSet 的查询方法:`QueryDataSet`
### 1.5.16
* 重构,合并 `Dapper-Extensions` 到 `DapperDal`,然后移除 `Dapper-Extensions`
### 1.5.15
* 删除方法 `QueryFirstOrDefault`,可以使用 `QueryFirst` 替换
* 添加重载方法 `OpenConnection`、`Execute`、`Query`, 支持传入其他 DB 连接串
### 1.5.14
* 添加逻辑删除或激活方法 `SwitchActive`
* 删除方法 `GetFirstOrDefault`,可以使用 `GetFirst` 替换
* 添加支持主键 ID 的重载方法 `Update`、`Delete`
* 配置项 `SoftDeleteProps` 迁移到 `DapperDal` 中,新添加配置项 `SoftActiveProps`
### 1.5.13
* 添加谓词表达式组合扩展方法(来自[alexfoxgill/ExpressionTools](https://github.com/alexfoxgill/ExpressionTools))
### 1.5.12
* 优化 `Exsit` 、`Count` 方法
### 1.5.11
* 优化更新方法,支持传递小写字段名
* 添加判断实体是否存在方法:`Exsit`
### 1.5.10
* 添加逻辑删除方法:`SoftDeleteById`
### 1.5.9
* 添加实体查询方法:`GetFirstOrDefault` 、`QueryFirstOrDefault` 、`QueryFirst`
### 1.5.8
* 添加SQL执行方法:`Execute` 、`ExecuteScalar`
### 1.5.7
* 添加实体查询方法:`GetFirst` 、`GetTop`
* 优化实体查询方法,添加实体集合返回前是否要缓冲的设置点
* 优化逻辑删除,添加更新属性及值的设置点
### 1.5.6
* 生成查询 SQL 时,添加 `WITH (NOLOCK)`
* 添加设置项:SQL 输出方法
### 1.5.5
* 添加逻辑删除方法 `SoftDelete`
### 1.5.4
* 表达式转换用 `QueryBuilder` 替换 `ExpressionVisitor` 实现,以支持多个查询条件(来自[ryanwatson/Dapper.Extensions.Linq](https://github.com/ryanwatson/Dapper.Extensions.Linq/blob/master/Dapper.Extensions.Linq/Builder/QueryBuilder.cs))
### 1.5.3
* 添加支持多个实体查询的 `Query` 方法
### 1.5.2
* 添加更新部分属性的 `Update` 方法(来自[vilix13/Dapper-Extensions](https://github.com/vilix13/Dapper-Extensions))
* 添加使用谓词、匿名对象或 `lambda` 表达式作条件的 `Update` 方法
### 1.5.1
* 整合 `Abp.Dapper`,为 `Dapper-Extensions` 添加 `lambda` 表达式功能(来自[Abp.Dapper](https://github.com/arbing/aspnetboilerplate/tree/master/src/Abp.Dapper))
License
-------------
Apache License 2.0