数据转换过程

前面已经解释了DTO的作用,但实现领域对象与DTO之间的转换是一件复杂的事件,因此可以建立一个数据转换器实现此功能。

在平常的工作里,不太多会把"订单管理系统"做成SOA的模式,因为在分布式系统中,数据的格式与定义大多数由部门之间协定,其中包含明确的规则。但由于条件的局限,在这里还是想以订单管理为例子,希望可以带给你一定的帮助。例子如下:在购物车结账,页面会包含用户基本信息,当前订单信息,订单明细信息等多个部分。

要完成数据转换,首先可以根据页面建立DTO对象,在分布式系统中,通常会把DTO对象放在一个独立的命名空间里,在这个实例里面称之为Business.TransferObject。DTO对象更多时候是面向表现层的需求而建立,这里由于表现层页面所需要的只是单个用户,单张订单的数据,所以在OrderDTO对象里会包含了用户信息和订单资料,也存在订单详细列List<OrderItemDTO>。当然,DTO的设计可以随着需求而修改。

在SOA系统里,DTO是远程服务数据的载体,所以会把DTO附上可序列化特性,这此例子中会使用WCF的数据契约实现OrderDTO和OrderItemDTO。

如图,要实现数据转换,就应该建立数据转换器。在这里OperationAssembler就是一个数据转换器,它是数据转换的核心,它是领域对象与DTO之间实现转换的工具。要在多个对象之间实现数据转换实在是一件非常麻烦的事,所以我一直提倡注意DTO对象的兼容性,使单个DTO对象可以适用于多个外观层,以减少数据转换所带来的麻烦。

复制代码
namespace Business.Service.ApplicationService
{
    public class OperationAssembler
    {
        //把领域对象转换成DTO
        public static OrderDTO GetOrderDTO(Order order,Person person)
        {
            OrderDTO orderDTO = new OrderDTO();
            if (person != null)
            {
                orderDTO.EMail = person.EMail.GetString();
                orderDTO.Address = person.Address.GetString();
                orderDTO.Name = person.Name.GetString();
                orderDTO.PersonID = person.ID;
                orderDTO.Point = person.Point.GetInt();
                orderDTO.Telephone = person.Telephone.GetString();
            }
            if (order != null)
            {
                orderDTO.PersonID = order.PersonID;
                orderDTO.Count = order.Count.GetInt();
                orderDTO.Delivery = order.Delivery.GetDateTime();
                orderDTO.Favorable = order.Favorable.GetDouble();
                orderDTO.Freightage = order.Freightage.GetDouble();
                orderDTO.OrderID = order.ID;
                orderDTO.OrderNumber = order.OrderNumber.GetString();
                orderDTO.Price = order.Price.GetDouble();
                orderDTO.TotalPrice = order.TotalPrice.GetDouble();
                var orderItemList = order.OrderItem.ToList();
                if (orderItemList.Count != 0)
                {
                    var orderItemDTO = new List<OrderItemDTO>();
                    foreach (var orderItem in orderItemList)
                        orderItemDTO.Add(GetOrderItemDTO(orderItem));
                    orderDTO.OrderItemList = orderItemDTO;
                }
            }
            return orderDTO;
        }

        public static OrderItemDTO GetOrderItemDTO(OrderItem orderItem)
        {
            OrderItemDTO orderItemDTO = new OrderItemDTO();
            orderItemDTO.Count = orderItem.Count.GetInt();
            orderItemDTO.Goods = orderItem.Goods.GetString();
            orderItemDTO.OrderID = orderItem.OrderID;
            orderItemDTO.OrderItemID = orderItem.ID;
            orderItemDTO.Price = orderItem.Price.GetDouble();
            return orderItemDTO;
        }

        //把DTO转换成多个对象
        public static void SetOrder(OrderDTO orderDTO, out Person person, out Order order)
        {
            person = new Person();
            person.EntityKey=new System.Data.EntityKey("BusinessContext.Person","ID",orderDTO.PersonID);
            person.Address = orderDTO.Address;
            person.EMail = orderDTO.EMail;
            person.ID = orderDTO.PersonID;
            person.Name = orderDTO.Name;
            person.Point = orderDTO.Point;
            person.Telephone = orderDTO.Telephone;

            order = new Order();
            order.EntityKey=new System.Data.EntityKey("BusinessContext.Order","ID",orderDTO.OrderID);
            order.Count = orderDTO.Count;
            if (orderDTO.Delivery.Year!=0001&&orderDTO.Delivery.Year!=9999)
                order.Delivery = orderDTO.Delivery;
            order.Favorable = orderDTO.Favorable;
            order.Freightage = orderDTO.Freightage;
            order.ID = orderDTO.OrderID;
            order.OrderNumber = orderDTO.OrderNumber;
            order.PersonID = orderDTO.PersonID;
            order.Price = orderDTO.Price;
            order.TotalPrice = orderDTO.TotalPrice;
            var orderItemDTOList = orderDTO.OrderItemList;
            if (orderItemDTOList.Count() != 0)
                foreach (var orderItemDTO in orderItemDTOList)
                    order.OrderItem.Add(GetOrderItem(orderItemDTO));
        }

        public static OrderItem GetOrderItem(OrderItemDTO orderItemDTO)
        {
            OrderItem orderItem = new OrderItem();
            orderItem.EntityKey = new System.Data.EntityKey("BusinessContext.OrderItem", "ID", orderItemDTO.OrderItemID);
            orderItem.Count = orderItemDTO.Count;
            orderItem.Goods = orderItemDTO.Goods;
            orderItem.ID = orderItemDTO.OrderItemID;
            orderItem.OrderID = orderItemDTO.OrderID;
            orderItem.Price = orderItemDTO.Price;
            return orderItem;
        }
    }
}

//数据传输对象 DTO
namespace Business.TransferObject
{
    [DataContract]
    public class OrderItemDTO
    {
        private int _orderItemID;
        private int _orderID;
        private string _goods;
        private double _price;
        private int _count;

        [DataMember]
        public int OrderItemID
        {
            get { return _orderItemID; }
            set { _orderItemID = value; }
        }
        ............
        ............
    }

    [DataContract]
    public class OrderDTO
    {
        private int _personID;
        private string _name;
        private string _address;
        private string _telephone;
        private int _point;
        private string _email;
        private int _orderID;
        private string _orderNumber;
        private int _count;
        private double _freightage;
        private double _favorable;
        private DateTime _delivery;
        private double _price;
        private double _totalPrice;
        private IList<OrderItemDTO> _orderItemDTOList;

        [DataMember]
        public int PersonID
        {
            get{return this._personID;}
            set{this._personID=value;}
        }
        ..........
        ..........
    }
}

通过数据转换器,可以顺利实现领域模型与DTO之间的转换,协调应用层服务的运行。

4. 应用层的发布

在开发SOA系统的时候,应用层的服务需要使用远程方法对外开放,在接收到请求的时候,它可以调用领域层服务获取运算结果,然后通过数据转换器OperationAssembler把运算结果转换成DTO,最后返还到表现层。在起初,我曾尝试对应每个应用层的对象建立一个远程接口,但经过多次重构以后,我觉得行程对象就是一个简单的对外接口,对象之间不存在什么逻辑关系。所以更简单的方法是使用外观模式,建立少数的几个远程服务类,把所有的应用层对象的方法都包含在内。

可以留意代码,OperationService包括了对Person模型和Order模型的所有操作。而且每个操作都只是简单地调用应用层服务 (ApplicationService) 获得计算结果,然后使用数据转换器 (OperationAssembler)转换数据,当中并不存在任何的业务逻辑。

复制代码
namespace Business.Service.ApplicationService
{
    [ServiceContract]
    public interface IOperationService
    {
        [OperationContract]
        int AddOrder(ref OrderDTO orderDTO);

        [OperationContract]
        int DeleteOrder(OrderDTO orderDTO);

        [OperationContract]
        int UpdateOrder(ref OrderDTO orderDTO);

        [OperationContract]
        IList<OrderDTO> GetOrderByPerson(int personID);

        [OperationContract]
        OrderDTO GetOrder(int orderID);

        [OperationContract]
        int AddPerson(ref OrderDTO orderDTO);

        [OperationContract]
        int UpdatePerson(ref OrderDTO orderDTO);

        [OperationContract]
        OrderDTO GetPerson(int personID);

        [OperationContract]
        IList<OrderDTO> GetPersonList();

        [OperationContract]
        OrderDTO Payment(int orderID);
    }

    public class OperationService:IOperationService
    {
        [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
        public int AddOrder(ref OrderDTO orderDTO)
        {
            OrderService orderService = new OrderService();
            Order order = GetOrder(orderDTO);
            int n = orderService.AddOrder(order);
            orderDTO = OperationAssembler.GetOrderDTO(order, null);
            return n;
        }

        [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
        public int DeleteOrder(OrderDTO orderDTO)
        {
            OrderService orderService = new OrderService();
            return orderService.DeleteOrder(GetOrder(orderDTO));
        }

        [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
        public int UpdateOrder(ref OrderDTO orderDTO)
        {
            OrderService orderService = new OrderService();
            Order order = GetOrder(orderDTO);
            int n = orderService.UpdateOrder(order);
            orderDTO = OperationAssembler.GetOrderDTO(order, null);
            return n;
        }
        ..............
        ..............
    }
}
相关推荐
知无不研1 分钟前
lambda表达式的使用(3)
开发语言·c++·lambda
数智化管理手记11 分钟前
海量数据如何沉淀有效数据资产?数据标准化治理方案如何搭建?
java·大数据·人工智能
cfm_291431 分钟前
SpringAI + Ollama 本地大模型
java·开发语言·人工智能·语言模型
鲸采云SRM采购管理系统1 小时前
采购管理系统哪家好?2026最新测评对比
java·服务器·数据库
C++ 老炮儿的技术栈2 小时前
基于Qt实现轻量化本地音乐播放器
开发语言·c++·qt·c·播放器·音乐
qq_448011162 小时前
C语言中的柔性数组
c语言·开发语言·柔性数组
小白学大数据2 小时前
长周期爬虫的数据一致性:断点续爬 + 事务回滚保障采集质量
开发语言·爬虫·测试工具
0x532 小时前
Java网络编程(二)
java·服务器·网络
zlinear数据采集卡2 小时前
D223上位机C#开发实战:从帧解析到波形显示的完整实现
开发语言·arm开发·嵌入式硬件·fpga开发·开源·c#
Flittly3 小时前
【雕虫大技】Agent 动态 Skill 供应链安全加固(三):输出校验与治理闭环实战
java·spring boot·spring