9.12、切面上下文(TangentDbContext)
切面上下文是一种全新的面向切面操作数据库方式。
什么是切面上下文
切面上下文是 Hoa Framework 框架独创的面向切面方式操作数据库方式,主要用来解决 sql 语句、存储过程、函数调用
情况。
可能有些时候我们避免不了写 sql
的方式(特别注意,除非 Linq/Lambda 方式不能做到,才用切面上下文),如:
传统写法(以后不推荐)
// sql方式
_testRepository.FromSql("select name from test where id=@id"
, new SqlParameter[]{ new SqlParameter("@id", 1) });
// 执行存储过程
_testRepository.SqlProcedureQuery("PROC_Name", new ProcModel(){});
// 执行函数
_testRepository.SqlFunctionQuery("Func_Name", new FuncModel(){});
上面的方式似乎没有上面问题,但是如果多个地方需要用到这些 sql
或 存储过程 或 函数
调用,就会散落到处都是,不利于维护。
所以,Hoa Framework 框架设计出全新的方式,主要用来解决上述代码多次调用散落问题。
如何使用(推荐)
第一步
定义一个接口(只需要接口),并继承 ITangentDependency
接口,如:IFallScatteredQuery
,如:
using Hoa.DbManager.Tangents;
namespace Hoa.Application
{
// 必须继承 ITangentDependency 接口
public interface IFallScatteredQuery: ITangentDependency
{
// 执行原始 sql 查询
[Sentence("select name from dbo.test where id=@id")]
string GetName(int id);
// 执行存储过程
[Procedure("PROC_Name")]
IEnumerable<Test> GetProcResult(object model);
// 执行函数
[ScalarFunction("Func_Name")]
int GetFuncReuslt(object model);
}
}
第二步
通过依赖注入 ITangentDbContext
切面上下文接口,并调用 For<T>
进行初始化,如:
using Hoa.Application;
using Hoa.DbManager.Tangents;
using Microsoft.AspNetCore.Mvc;
namespace Hoa.Web.Host.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class HoaController : ControllerBase
{
// 构造函数初始化
private readonly IFallScatteredQuery _tangent;
public HoaController(ITangentDbContext tangentDbContext)
{
// 解析接口信息
_tangent = tangentDbContext.For<IFallScatteredQuery>();
}
[HttpGet]
[Route(nameof(Test))]
public string Test()
{
// 执行sql
var name = _tangent.GetName(1); // 自动查询数据库
// 执行存储过程
var tests = _tangent.GetProcResult(new { name = "Monk" });
// 执行函数
var num = _tangent.GetFuncReuslt(new { id = 10});
return "Powered by Monk";
}
}
}
神奇吧!通过这种方式,Hoa Framework 会自动查询数据库并转换成指定的结果。再也不怕代码难维护了!😘
特性说明
目前 切面上下文支持 三种 特性解析:
[Sentence(sql, DbContextIdentifier=)]
:支持传入sql
语句,支持命令参数
防止 sql 注入。[Procedure(name, DbContextIdentifier=)]
:支持传入存储过程名称[ScalarFunction(name, DbContextIdentifier=)]
:支持传入函数名称
其中 DbContextIdentifier
参数是 Type
类型,也就是 数据库上下文标识类。见 9.11、多上下文、读写分离 章节
支持返回值
TangentDbContext
几乎支持所有返回值类型,如:
Object
除了
Enum
以外的所有值类型和string
类型,如:int, bool, decimal, string, float, long等等
所有可枚举集合类型,包括
Array
,List
,IEnumerable
等DataTable
和DataSet
类型ValueTuple
元组类型
支持元组返回多个值
using Hoa.DbManager.Tangents;
using System.Collections.Generic;
using System.Data;
namespace Hoa.Application
{
public interface IFallScatteredQuery : ITangentDependency
{
[Sentence(@"
select * from dbo.brokers;
select * from dbo.brokers where id > @id;
select * from dbo.brokers where name = @name
")]
DataSet GetDataSet(int id, string name);
[Sentence(@"
select top 2 * from dbo.brokers;
select * from dbo.brokers where id > @id;
select * from dbo.brokers where name = @name
")]
(IEnumerable<Broker> brokers1, IEnumerable<Broker> brokers2, IEnumerable<Broker> brokers3) GetValueTuple(int id, string name);
}
}
var dataset = _tangent.GetDataSet(1, "Monk2");
var (broker1, borker2, borker3) = _tangent.GetValueTuple(0, "Monk");
支持复杂类型返回并自动映射
[Procedure("PROC_Name", SourceType = typeof((A, IEnumerable<B>, IEnumerable<C>, IEnumerable<D>)))]
(ADto a, IEnumerable<BDto> b, IEnumerable<CDto> c, IEnumerable<DDto> d) PRGetPersonDemographicDetail(Parameter_PersonID parameter);
config.ForType<A, ADto>().ConvertSourceMemberUnderlineSplitNameToCamelCase();
config.ForType<(A a, IEnumerable<B> b, IEnumerable<C> a, IEnumerable<D> d), (ADto aDto, IEnumerable<BDto> bDto, IEnumerable<CDto> cDto, IEnumerable<DDto> dDto)>()
.ConvertSourceMemberUnderlineSplitNameToCamelCase()
.Map(dest => dest.aDto, src => src.a)
.Map(dest => dest.aDto.B, src => src.b)
.Map(dest => dest.aDto.C, src => src.c)
.Map(dest => dest.aDto.D, src => src.d);
多上下文配置
切面上下文还支持多上下文操作,如:
using Hoa.Core;
using Hoa.Core.Web.Entities;
using Hoa.DbManager.Tangents;
using System.Collections.Generic;
namespace Hoa.Application
{
public interface IFallScatteredQuery : ITangentDependency
{
[Procedure("PROC_Name", DbContextIdentifier = typeof(OtherDbContextIdentifier))]
IEnumerable<Entity> GetEntities(Model parameter);
}
}
自动映射到Dto类型
通常我们数据库返回的是我们的实体模型,这个时候,我们还需要手动的调用 .Adapt<DtoType>
到 DtoType
类型,所以,切面上下文提供了一种更加便捷的方式,只需要指定 SouceType
即可,如:
using Hoa.Core;
using Hoa.Core.Web.Entities;
using Hoa.DbManager.Tangents;
using System.Collections.Generic;
namespace Hoa.Application
{
public interface IFallScatteredQuery : ITangentDependency
{
// 设置SourceType 为执行真正的返回值,然后方法的返回值设置为Dto即可
// 实际上内部会自动帮你将 SourceType 类型 Adapt 到 方法的返回值类型
[Procedure("PROC_Name", SouceType = typeof(IEnumerable<Entity>))]
IEnumerable<Dto> GetDtos(Model parameter);
}
}
特别注意
不建议在切面上下文中做 增删改操作(即使框架本身支持)!!!!
最后更新于
这有帮助吗?