zoukankan      html  css  js  c++  java
  • 思考一种好的架构(七)

    先来看看商品业务服务库

    有控制器、有实体、有自己的服务、有配置

    依赖:

     这也是所有业务服务库的大体依赖

    必选:

    中介者服务(Mediator)

    数据库访问(ORM.Chloe)

    路由(Route)

    可选:

    对象映射服务(AutoMapper)

    扫描服务(ReferenceScan)

    库存业务服务库(Stock)

    控制器:

     [ApiController]
        [APIRouth("Product")]
        public class ProductController : Controller
        {
            IProduct productServer;
            public ProductController(IProduct productServer) {
                this.productServer = productServer;
            }
            /// <summary>
            /// 获取全部商品信息
            /// </summary>
            /// <param name="maxNumber">库存最大数量</param>
            /// <returns></returns>
            [HttpGet]
            public IActionResult GetAll(int? maxNumber)
            {
                var result =productServer.GetAll(maxNumber);
                return Json(result);
            }
            /// <summary>
            /// 获得单个商品信息
            /// </summary>
            /// <param name="ID">商品ID</param>
            /// <returns></returns>
            [HttpGet]
            public IActionResult Get(int ID=0)
            {
                var result = productServer.GetSingle(ID);
                return Json(result);
            }
    
        }

    其中 

    APIRouth特性头是编写的一个特性
     /// <summary>
        /// API路由
        /// </summary>
        public class APIRouth : Microsoft.AspNetCore.Mvc.RouteAttribute
        {
            /// <summary>
            /// 设计一个API的路由
            /// </summary>
            /// <param name="area">区域名称</param>
            public APIRouth(string area) : base($"api/{area}/[controller]/[action]")
            {
    
            }
        }

    这是为了达到统一API路径的目的

    控制器很简单

    只执行调用IProduct 服务的功能,在后续开发中,他也是比较贫血的一层

    可以预料的是,它的作用仅仅只是为了提供一个访问入口且写明注释,并调用了服务

    至于表单验证,响应模型之类的我们将会在中间件中完成,可以会有困难,但还是尽量中间件中完成,如果不行那么将会仍在过滤器或者父类控制器完成,尽量保证不会在业务中出现这种重复性代码

    实体:

     [Table(Name = "Product")]
        public class ProductEntity
        {
            [ColumnAttribute(IsPrimaryKey = true)]
            [AutoIncrement]
            public int ID { get; set; }
    
            public string Title { get; set; }
    
            public string Describe { get; set; }
        }

     业务处理服务:

      public class ProductServer : IProduct
        {
            IDbContext DC;
            IStock stock;
            IMapper mapper;
            public ProductServer(IDbContext DC, IStock stock,IMapper mapper) {
                this.DC = DC;
                this.stock = stock;
                this.mapper = mapper;
            }
            public List<ProductInfoDTO> GetAll(int? maxNumber)
            {
                var result = DC.Query<ProductEntity>().RightJoin(stock.StockNumberQuery(null, maxNumber), (c, z) =>
                c.ID.Equals(z.ProductID))
                    .Select((x, z) => new ProductInfoDTO()
                    {
                        Describe = x.Describe,
                        ID = x.ID,
                        StockNumber = z.Number,
                        Title = x.Title
    
                    });
                return result.ToList();
            }
    
            public ProductInfoDTO GetSingle(int ID)
            {
               return DC.Query<ProductEntity>().InnerJoin(stock.GetSingle(ID), (c, z) => c.ID.Equals(z.ProductID)).Select((x, z) => new ProductInfoDTO()
                {
                    Describe = x.Describe,
                    ID = x.ID,
                    StockNumber = z.Number,
                    Title = x.Title
    
                }).FirstOrDefault(x => x.ID.Equals(ID)); ;
            }
        }
    DC   数据库上下文
    stock 库存服务
    mapper (AutoMapper) 对象映射服务


    这里有一个跨服务的联合查询
    在数据库中 商品和库存是两个关联的表
    代码中通过
    RightJoin
    InnerJoin
    来进行链表查询

      public interface IStock
        {
            /// <summary>
            /// 库存查询
            /// </summary>
            /// <param name="minNumber">最小库存</param>
            /// <param name="maxNumber">最大库存</param>
            /// <returns></returns>
            IQuery<StockDTO> StockNumberQuery(int? minNumber, int? maxNumber);
    
            /// <summary>
            /// 库存查询
            /// </summary>
            /// <param name="product">商品ID</param>
            /// <returns></returns>
            IQuery<StockDTO> GetSingle(int productID);
    
          /// <summary>
          /// 消减库存
          /// </summary>
          /// <param name="productID">商品ID</param>
          /// <param name="number">数量</param>
          /// <returns></returns>
            bool ReducedInventory(int productID,int number);
        }
    跨库查询也是一个非常大的问题,这里我们还只是一个同数据库不同服务的跨服务查询,后续的跨服务跨库查询才是真正难以解决的问题

    库存服务返回了一个IQuery查询对象,方便Chloe进行链表操作
    最后在Product服务中去执行关联和返回查询实体,
    这里没有用到mapper,因为Chloe的Select已经足够使用,没必要再去添一行代码去使用mapper

    启动执行:
      public class StartExecute : BaseStartExecute
        {
            public override void Execute()
            {
                MapperPost.CreateMap(x => x.CreateMap<ProductInfoDTO, ProductEntity>());
                MapperPost.CreateMap(x => x.CreateMap<ProductEntity, ProductInfoDTO>().ForMember(dest => dest.StockNumber, opt => opt.Ignore()));
            }
        }
    Mapper需要在启动的时候也就是ConfigureServices函数中就进行调用,这会有个问题,大家争抢ConfigureServices函数执行顺序,变得非常难以管理,所以
    StartExecute出现了,它会在所有服务调用ConfigureServices前调用,并逐个执行Execute函数,这样一来,就不用关注ConfigureServices函数的执行顺序啦
    具体代码后续在说


    启动类:
     public static class Startup
        {
            public static void ConfigureServices(IServiceCollection services)
            {
                services.AddTransient<IProduct, ProductServer>();
    
            }
    
            public static void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                
            }
        }
    在这里注册了IProduct服务,
    IProduct服务是在中介者服务中的,中介者服务会在后续说到






     
     
  • 相关阅读:
    SQL Server Audit监控触发器状态
    SQL Server 数据变更时间戳(timestamp)在复制中的运用
    SQL Server 更改跟踪(Chang Tracking)监控表数据
    SQL Server 变更数据捕获(CDC)监控表数据
    SQL Server 事件通知(Event notifications)
    SQL Server 堆表行存储大小(Record Size)
    SQL Server DDL触发器运用
    SQL Server 默认跟踪(Default Trace)
    SQL Server 创建数据库邮件
    SQL Server 跨网段(跨机房)FTP复制
  • 原文地址:https://www.cnblogs.com/AnAng/p/12611146.html
Copyright © 2011-2022 走看看