引文
hi, 大家好, 我是三合. 不知各位有没有想过, 如果能把数据库操作和 http 访问都统一封装成接口 (interface) 的形式,
然后接口对应的实现类由框架去自动生成, 那么必然能大大降低工作量, 因为不需要去写很多重复的代码了, 还有一个好处是, 都是提供接口, 我们把原来数据库操作的部分, 改成 http 访问, 对于业务层来说, 是无感的, 因为接口和方法都没变. 致力于降低上手 net core 的门槛, 我开源了 https://github.com/TripleView/SummerBoot 项目, 下面让我们来看一下效果.
数据库表对应实体类, 这些都是常规操作, 略过
重头戏, 如何写接口, 以一个简单的购物功能为例子
数据库访问
订单详情仓储
订单仓储
http 访问
控制器中进行构造函数注入
实际调用
- /// <summary>
- /// 添加订单
- /// </summary>
- /// <param name="dto"></param>
- /// <returns></returns>
- [HttpPost("AddOrder")]
- public async Task<IActionResult> AddOrder([FromBody]AddOrderDto dto)
- {
- if (dto?.ProductList==null) return BadRequest("参数不能为空");
- Uow.BeginTransaction();
- try
- {
- var orderHeader = new OrderHeader
- {
- CreateTime = DateTime.UtcNow,
- CustomerNo = dto.CustomerNo,
- State = 1,
- OrderNo = Guid.NewGuid().ToString("N")
- };
- await OrderHeaderRepository.InsertAsync(orderHeader);
- var orderDetailList = new List<OrderDetail>();
- // 总消费金额
- var totalAmount = 0m;
- dto.ProductList.ForEach(it =>
- {
- var orderDetail = new OrderDetail
- {
- OrderHeaderId = orderHeader.Id,
- ProductNo = it.ProductNo,
- ProductName = it.ProductName,
- Quantity = it.Quantity,
- Price = it.Price
- };
- orderDetailList.Add(orderDetail);
- totalAmount += it.Quantity * it.Price;
- });
- await OrderDetailRepository.BatchInsertAsync(orderDetailList);
- // 更新用户消费金额
- var success = await CustomerRepository.UpdateCustomerAmount(dto.CustomerNo, totalAmount);
- if (!success)
- {
- Uow.RollBack();
- return BadRequest();
- }
- }
- catch (Exception e)
- {
- Uow.RollBack();
- }
- Uow.Commit();
- return Ok();
- }
- /// <summary>
- /// 删库跑路
- /// </summary>
- /// <returns></returns>
- [HttpGet("DeleteDatabase")]
- public async Task DeleteDatabase()
- {
- await OrderHeaderRepository.DeleteAllOrder();
- }
- /// <summary>
- /// 根据会员编号取消订单
- /// </summary>
- /// <param name="customerNo"></param>
- /// <returns></returns>
- [HttpGet("CancelOrderByCustomerNo")]
- public async Task<bool> CancelOrderByCustomerNo(string customerNo)
- {
- var count = await OrderHeaderRepository.CancelOrderByCustomerNoAsync(customerNo);
- return count> 0;
- }
- /// <summary>
- /// 分页, 根据会员编号获取消费详情
- /// </summary>
- /// <param name="customerNo"></param>
- /// <returns></returns>
- [HttpGet("QueryOrderDetailByCustomerNoByPage")]
- public async Task<Page<OrderDetail>> QueryOrderDetailByCustomerNoByPage(int pageNumber,int pageSize, string customerNo)
- {
- var page=new Pageable(pageNumber,pageSize);
- var result = await OrderDetailRepository.GetOrderDetailByCustomerNoByPageAsync(page,customerNo);
- return result;
- }
- /// <summary>
- /// 根据会员编号获取消费详情
- /// </summary>
- /// <param name="customerNo"></param>
- /// <returns></returns>
- [HttpGet("QueryOrderDetailByCustomerNo")]
- public async Task<List<OrderDetail>> QueryOrderDetailByCustomerNo(string customerNo)
- {
- var result= await OrderDetailRepository.GetOrderDetailByCustomerNoAsync(customerNo);
- return result;
- }
动态生成接口实现类的原理
最开始写的时候, 思路是, 采用 AOP 思想, castle 动态生成接口实现类, 实现类里的方法都没有具体实现, 然后在切面里对方法进行拦截并且模拟方法的实现, 提供返回值, java 中很多骚操作就是这么实现的, 但是后来发现在. net
中这种实现方式有很大的弊端, 因为. net 有异步方法, 而 castle 对于异步方法的支持是很弱的, 不足以实现最开始的设想, 于是, 我换了一种思路, 在数据库操作和 http 调用中, 抛开动态实现类这个壳子, 具体执行操作的类是恒定不变的,
那么利用 emit 技术动态路由到要执行的方法就行了.
写在最后
如果这篇文章对你有所启发不妨点个赞吧.
GitHub 地址: https://github.com/TripleView/SummerBoot , 欢迎 star!
QQ 群: 799648362
nuget 包: SummerBoot
来源: https://www.cnblogs.com/hezp/p/12747340.html