Asp.net Core Series - 3. field, warehousing, service is simple to achieve

ChuanGoing 2019-11-11 

   Part distance of nearly two months, on the one hand because the other things came up when, on the other hand is the lack of preparation before, there are several places on the field did not want to drive transparent, there is no continuation code word. Currently the network includes most of the garden Domain Driven Design article about storekeeper layer are not described in detail, but simply in passing: the drive does not care about the specific areas of persistent how landing. However, as a "human ape" is not open around the inevitable persistence. Benpian will briefly introduce the use of this lightweight ORM Dapper how to implement persistence.

Benpian learning curve:

1. Domain Model

2. Storage areas

3. Simple service implementation

Domain Model Design

  I use a common business model to introduce electric business domain model design, due to limited space, here introduces orders and order details model, based on the following business:

1. generate the order number when creating an order to calculate the total price of goods while generating the order details.

2. Obtain order information according to the order number

  My case essentially covers several major areas of the model portfolio: field - entity - the value of the object, these basic concepts is not elaborated here, found the garden a lot.

public partial class Order : DomainEntity<Guid>
    {
        /// <summary>
        /// 订单流水号
        /// </summary>
        public string Sn { get; private set; }
        /// <summary>
        /// 总价
        /// </summary>
        public decimal TotalPrice { get; private set; }
        /// <summary>
        /// 状态
        /// </summary>
        public OrderStatus Status { get; Private  SET ;}
         ///  <Summary> 
        /// payment time
         ///  </ Summary> 
        public  Long PaymentTime { GET ; Private  SET ;}
         ///  <Summary> 
        /// expiration time
         ///  </ Summary > 
        public  Long ExpireTime { GET ; Private  SET ;}
         ///  <Summary> 
        /// Note
         ///  </ Summary> 
        public  String the Description { GET ;private set; }
        /// <summary>
        /// 用户
        /// </summary>
        public Guid UserId { get; private set; }

        public string Adress { get; private set; }

        /// <summary>
        /// 订单明细
        /// </summary>
        [Ignore]
        public List<OrderItem> OrderItems { get; private set; }
    }
Order form
 public partial class OrderItem : Entity<Guid>
    {
        /// <summary>
        /// 订单编号
        /// </summary>
        public Guid OrderId { get; private set; }
        /// <summary>
        /// 商品编号
        /// </summary>
        public Guid ProductId { get; private set; }
        /// <summary>
        /// 商品单价
        /// </summary>
        public decimal Price { get; private set; }
        /// <summary>
        /// 数量
        /// </summary>
        public int Count { get; private set; }
        /// <summary>
        /// 加入时间
        /// </summary>
        public long JoinTime { get; private set; }
    }
order details

Order class can be seen as DomainEntity (Field Entity - aggregate root), OrderItem of the Entity (entity), Order, and a service aggregation OrderItem composition. Why do you divide it? There are two reasons:

1. The present embodiment does not involve complicated operations, there is no direct service operation for the Order Details

2. Order Details depend on the order, the order life cycle along with the body produce and fade away

 Orders and Order Details are designed to be "partial", because so far, our entity class or POCO, also known as anemia model. Therefore, in order to impart vitality model, we need to add some behavior:

public partial class Order
    {
        public void Add(Guid userId, Adress adress, string description, List<OrderItem> orderItems)
        {
            Sn = Guid.NewGuid().ToString("N");
            TotalPrice = orderItems.Sum(i => i.Price * i.Count);
            Status = OrderStatus.TobePaid;
            ExpireTime = DateTimeOffset.Now.AddMinutes(-30).ToUnixTimeMilliseconds();
            UserId = userId;
            Adress = adress.ToString();
            Description = description;
            orderItems.ForEach(i =>
            {
                i.SetOrder(this);
            });
            SetItems(orderItems);
        }

        public void Pay()
        {
            Status = OrderStatus.Paid;
            PaymentTime = DateTimeOffset.Now.ToUnixTimeMilliseconds();
        }

        public void SetItems(List<OrderItem> orderItems)
        {
            OrderItems = orderItems;
        }
    }
Orders behavior

In this way, we are given a certain behavior to the field.

Field warehousing

In conjunction with Part I Preliminary Asp.net Core Series --2.ORM: Dapper achieve MySql databases of various types of operating warehousing examples presented here as a separate domain model design "field storage layer"

public class OrderRepository : DapperRepository<Order, Guid>, IOrderRepository
    {
        public OrderRepository(IComponentContext container, IDapperDbContext dbContext)
            : base(container, dbContext)
        {

        }

        public Order GetBySn(string sn)
        {
            var order = QuerySingleOrDefault<Order>("SELECT * FROM `Order` WHERE `Sn`=@Sn;", new
            {
                Sn = sn
            });
            if (order != null)
            {
                order.SetItems(Query<OrderItem>("SELECT * FROM `OrderItem` WHERE `OrderId`=@OrderId;", new
                {
                    OrderId = order.Id
                }).ToList());
            }
            return order;
        }
    }
Field warehousing

Field warehousing implements the interface defined in the Domain

 public interface IOrderRepository : IRepository<Order, Guid>, IScopeInstance
    {
        Order GetBySn(string sn);
    }
Orders Warehouse interface definition

When Notably, this field storage layer plays a role of connecting the isolation areas directly dependent layer for persistence.

Simple service implementation

    Next, we realize how persistent data storage business in the field of call service layer. New Application project:

 

 Orders defined interface services

public interface IOrderService : IScopeInstance
    {
        void Add(OrderViewModel order);
        OrderViewResult Get(string sn);
    }

Orders service implementation

 public void Add(OrderViewModel view)
        {
            if (view == null) new Exception("参数无效");
            var order = new Order();
            Mapper.Map(view, order);

            order.Add(view.UserId, view.Adress, view.Description, order.OrderItems);
            _repo.Insert(order);
            order.OrderItems.ForEach(i => _itemRepo.Insert(i));
        }

        public OrderViewResult Get(string sn)
        {
            var order = _repo.GetBySn(sn);

            OrderViewResult result = new OrderViewResult ();
            return order == null ? zero : Mapper.Map (order, result); 
        }

In Webapi controller project folder under the new OrderController

public class OrderController : Controller
    {
        private readonly IOrderService _service;

        public OrderController(IOrderService service)
        {
            _service = service;
        }

        [HttpPost]
        public void Add([FromBody]OrderViewModel order)
        {
            _service.Add(order);
        }

        [HttpGet]
        public OrderViewResult Get([FromQuery]string sn)
        {
            return _service.Get(sn);
        }
    }

See yesterday's specific code source code links

In this way, we achieve a persistent domain model.

review

  Recall In this part, were introduced: the domain model, the field of warehousing, simple service and then use postman simulate http request demonstrates to create and access data.

  Benpian simply describes the services sector and related concepts, followed by the opportunity to do a detailed discussion, will introduce the next log module and permissions module.

Code

  Benpian Github source involved in the https://github.com/ChuanGoing/Start.git   can be found in Domain branch.

Guess you like

Origin www.cnblogs.com/ChuanGoing/p/11624228.html