10.2 Dapper 集成
📝 模块更新日志
在 Furion 包中默认集成了 EFCore,如果不使用 EFCore,可安装纯净版 Furion.Pure 代替 Furion。
10.2.1 关于 Dapper
Dapper 是.NET/C# 平台非常优秀的 微型 ORM 框架,主要是为 ADO.NET 操作对象提供扩展能力,推崇原生 sql 操作法。
Dapper 官方仓库地址:https://github.com/StackExchange/Dapper
10.2.2 如何集成
在 Furion 框架中,已经推出 Dapper 扩展包 Furion.Extras.DatabaseAccessor.Dapper。
10.2.2.1 注册 Dapper 服务
使用非常简单,只需要在 Startup.cs 中添加 services.AddDapper(connStr, SqlProvider) 即可。如:
services.AddDapper("Data Source=./Furion.db", SqlProvider.Sqlite);
// 更多配置,仅 v3.4.3+ 版本有效
servers.AddDapper("Data Source=./Furion.db", SqlProvider.Sqlite, () => {
DefaultTypeMap.MatchNamesWithUnderscores = true;
})
10.2.2.2 安装对应的数据库提供器
SqlServer:Microsoft.Data.SqlClientSqlite:Microsoft.Data.SqliteMySql:MySql.DataNpgsql:NpgsqlOracle:Oracle.ManagedDataAccess.CoreFirebird:FirebirdSql.Data.FirebirdClient- 达梦
Dm:DM.DmProviderhttps://eco.dameng.com/download/ - 人大金仓
Kdbndp:Kdbndp(NuGet包为:Kdbndp_V9)
在 Furion 框架中,推荐将扩展包 Furion.Extras.DatabaseAccessor.Dapper 安装到 Furion.Core 层中。
10.2.2.3 各类数据库连接字符串配置示例
Sqlite:Data Source=./Furion.dbMySql:Data Source=localhost;Database=Furion;User ID=root;Password=000000;pooling=true;port=3306;sslmode=disabled;CharSet=utf8;SqlServer:Server=localhost;Database=Furion;User=sa;Password=000000;MultipleActiveResultSets=True;Encrypt=True;TrustServerCertificate=True;Oracle:User Id=orcl;Password=orcl;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=orcl)))PostgreSQL:PORT=5432;DATABASE=postgres;HOST=127.0.0.1;PASSWORD=postgres;USER ID=postgres;- 达梦
Dm:Server=localhost;User Id=SYSDBA;PWD=SYSDBA;DATABASE=Furion; - 人大金仓
Kdbndp:Server=localhost;User ID=SYSTEM;Password=MANAGER;Database=Furion;Port=54328
10.2.3 基本使用
在使用之前,我们可以通过构造函数注入 IDapperRepository 或 IDapperRepository<TEntity> 接口,如:
- 非泛型版本
private readonly IDapperRepository _dapperRepository;
public PersonService(IDapperRepository dapperRepository)
{
_dapperRepository = dapperRepository;
}
- 泛型版本
private readonly IDapperRepository<Person> _personRepository;
public PersonService(IDapperRepository<Person> personRepository)
{
_personRepository = personRepository;
}
10.2.3.1 sql 操作
var data = _dapperRepository.Query("select * from person");
var data = await _dapperRepository.QueryAsync("select * from person");
var data = _dapperRepository.Query<Person>("select * from person");
var guid = Guid.NewGuid();
var dog = _dapperRepository.Query<Dog>("select Age = @Age, Id = @Id", new { Age = (int?)null, Id = guid });
var count = _dapperRepository.Execute(@"insert MyTable(colA, colB) values (@a, @b)",
new[] { new { a=1, b=1 }, new { a=2, b=2 }, new { a=3, b=3 } }
);
var user = _dapperRepository.Query<User>("spGetUser", new {Id = 1},
commandType: CommandType.StoredProcedure).SingleOrDefault();
用法和官方一致,此处不再举更多例子。
10.2.3.2 <TEntity> 操作
Furion 框架提供了 IDapperRepository 和 IDapperRepository<TEntity> 两个操作仓储,后者继承前者。使用如下:
var person = personRepository.Get(1);
var persons = personRepository.GetAll();
var effects = personRepository.Insert(person);
var effects = personRepository.Update(person);
var effects = personRepository.Delete(person);
var effects = personRepository.Insert(persons); // 插入多个
var effects = personRepository.Update(persons); // 更新多个
var effects = personRepository.Delete(persons); // 删除多个
var effects = await personRepository.InsertAsync(person);
10.2.4 高级使用
IDapperRepository 和 IDapperRepository<TEntity> 仓储提供了 Context 和 DynamicContext 属性,该属性返回 IDbConnection 对象。
拿到该对象后,我们就可以操作 Dapper 提供的所有操作了,如:
10.2.4.1 查询一对一
var sql =
@"select * from #Posts p
left join #Users u on u.Id = p.OwnerId
Order by p.Id";
var data = dapperRepository.Context.Query<Post, User, Post>(sql, (post, user) => { post.Owner = user; return post;});
var post = data.First();
10.2.4.2 查询多个结果
var sql =
@"
select * from Customers where CustomerId = @id
select * from Orders where CustomerId = @id
select * from Returns where CustomerId = @id";
using (var multi = dapperRepository.Context.QueryMultiple(sql, new {id=selectedId}))
{
var customer = multi.Read<Customer>().Single();
var orders = multi.Read<Order>().ToList();
var returns = multi.Read<Return>().ToList();
// ...
}
10.2.4.3 更多操作
var shapes = new List<IShape>();
using (var reader = dapperRepository.Context.ExecuteReader("select * from Shapes"))
{
var circleParser = reader.GetRowParser<IShape>(typeof(Circle));
var squareParser = reader.GetRowParser<IShape>(typeof(Square));
var triangleParser = reader.GetRowParser<IShape>(typeof(Triangle));
var typeColumnIndex = reader.GetOrdinal("Type");
while (reader.Read())
{
IShape shape;
var type = (ShapeType)reader.GetInt32(typeColumnIndex);
switch (type)
{
case ShapeType.Circle:
shape = circleParser(reader);
break;
case ShapeType.Square:
shape = squareParser(reader);
break;
case ShapeType.Triangle:
shape = triangleParser(reader);
break;
default:
throw new NotImplementedException();
}
shapes.Add(shape);
}
}
10.2.5 反馈与建议
给 Furion 提 Issue。
想了解更多 Dapper 知识可查阅 Dapper 官网。