前言
可以说,订单管理模块是PetShop4中最值得去研究的模块了.因为它使用中多个重要的技术:工厂模式设计,策略模式设计,尤其是采用了订单的异步处理功能,Windows消息机制等高级技术.
订单的数据数设计
为了提高访问速度,PetShop4的订单数据是单独保存在一个数据库中的,这个数据库叫做:MSPetShop4Orders.在本系列博文第一篇中,我们就对该数据库做过比较详细的分析.这里不再多加描述.
订单的数据访问层
订单模块和购物篮模块一样,采用的是典型的工厂模式.
首先,分析订单的实体类,在PetShop4中,订单分为两部分,一部分是订单基本信息,保存在Order表中,另一部分是订单的详细商品信息,保存在LineItem表中,根据实体类和表的关系,因此实体类也分为两个:LineItemInfo类和OrderInfo类.它们的属性分别对应数据库中的两个表的字段.这些实体类都位于Model项目下.
接着,我们分析一下订单的数据访问类.数据访问类是DAL类的集中体现,系统中只用了一个类Order类,专门处理与订单有关的操作.以SQLServerDAL项目下的Order类为例,以下是Order类的结构如下图:
订单的业务逻辑层
业务逻辑层的提交订单分为两种方式:同步方式和异步方式.
同步是指用户提交订单后,把数据插入到表中后,再执行下面的操作;而异步是指用户提交订单后,数据的处理交给后台的MSMQ(消息队列)去处理,用户可以继续操作下面的内容,不需要等待本次订单完成.显然,异步处理可以大大提高操作的效率,不会影响用户折其他操作.
订单管理的BLL实现过程大致如下图所示:
与订单操作业务逻辑有于的类有三个:Order,OderAsynchronous和OrderSynchronous,均位于BLL项目下.
Order类,主要完成对订单的插入和获取订单信息的操作,具体结构如下图:
其中的几个静态变量的声明很修复注意:
// Using a static variable will cache the Order Insert strategy object for all instances of Order
// We implement it this way to improve performance, so that the code will only load the instance once
private static readonly PetShop.IBLLStrategy.IOrderStrategy orderInsertStrategy = LoadInsertStrategy();
//create a message query for an order.
private static readonly PetShop.IMessaging.IOrder orderQueue = PetShop.MessagingFactory.QueueAccess.CreateOrder();
// Get an instance of the Order DAL using the DALFactory
// Making this static will cache the DAL instance after the initial load
private static readonly IOrder dal = PetShop.DALFactory.DataAccess.CreateOrder();
而LoadInsertStrategy()方法将给我们返回一个策略算法实例.通过读取配置文件的方式,自动判断是采用同步处理还是异步处理.
OrderSynchronous类,采用同步处理的方法操作订单,此类和异步处理类OderAsynchronous一起继承自IOrderStrategy接口,IOrderStrategy接口位于IBLLStrategy项目下.OrderSynchronous类的代码如下:
public class OrderSynchronous : IOrderStrategy {
// Get an instance of the Order DAL using the DALFactory
// Making this static will cache the DAL instance after the initial load
private static readonly PetShop.IDAL.IOrder dal = PetShop.DALFactory.DataAccess.CreateOrder();
///
using (TransactionScope ts = new TransactionScope(TransactionScopeOption.Required)) {
dal.Insert(order);
// Update the inventory to reflect the current inventory after the order submission
Inventory inventory = new Inventory();
inventory.TakeStock(order.LineItems);
// Calling Complete commits the transaction.
// Excluding this call by the end of TransactionScope's scope will rollback the transaction
ts.Complete();
}
}
}
代码中实现了父接口中定义的insert()方法,并通过一个事务更新商品的数量.
比较OderAsynchronous类的代码:
public class OrderAsynchronous : IOrderStrategy
{
// Get an instance of the MessagingFactory
// Making this static will cache the Messaging instance after the initial load
private static readonly PetShop.IMessaging.IOrder asynchOrder = PetShop.MessagingFactory.QueueAccess.CreateOrder();
///
asynchOrder.Send(order);
}
}
insert()方法将要处理的订单操作完全交给了消息队列去处理了.asynchOrder在类中是一个MSMQ对象,通过些对象的"Send"方法实现消息的发送,消息保存在系统的MSMQ中.
MSMQ简介
MSMQ,微软消息队列,它使不在同一时间运行的程序,可以在不同各类的网络和可能暂时脱机的系统间进行通信.可用于同步和异步消息传递的解决方案.消息处理是异步处理的关键一点.MSMQ一个Windows组件,系统默认不安装,可通过"添加删除应用程序"实现安装.
消息处理类位于"System.Messaging"命名空间中.下面介绍几个重要的对象和方法:
1,初始化消息队伍代码:
MessageQueue Mq=new MessageQueue("hostname//quequname");
消息队列中需要指明队列所以在机器和队列名.
2,也可以使用Path属性引用消息队列.
MessageQueue Mq=new MessageQueue();
Mq.Path="hostname//quequname";
3,使用Create方法以编程方式创建队列:
MessageQueue Mq=new MessageQueue.Create("hostname//quequname");
4,发送信息
Mq.Send(1000);
Mq.Send("Test");
5,接收消息,Recerve方法,接收消息的同时永久地从队列中删除消息,Peek方法接收后不从消息队列中移除消息.
Mq.Recerve();
Mq.Peek();
PetShop4中使用消息接口的设计,所有与消息相关的处理类都存放在IMessaging和MSMQMessaging项目下,在IMessaging项目中定义了IOrder接口,在MSMQMessaging中的Order类中实现了该接口,且Order类还继承了类PetShopQueue,以下是Order结构图:
Order类是实现消息队列的关键类,其中的Send方法和Receive方法并没有实现的完成队列操作,而是调用其父类PetShopQueue中的方法来完成.
实现订单的异步提交功能
前面研究了系统中要用到的实现异步提交的消息处理类,接下来将真正实现订单的异步提交功能
首先,创建MSMQ:在安装了MSMQ后,在计算机管理里可以找到“消息队列”结点,新建一个“专用队列”,命名要与配置文件中定义的一样,选中“事务性”。
接着,修改配置文件,实现异步功能。
下面,创建一个Windows服务实现后台订单处理,该服务程序根据指定的时间间隔,从队列中获取数据,执行订单的提交工作,这一切都在后台自动完成。注意,该服务采用了多线程操作。使用“InstallUtil”命令加载服务程序。并在Windows服务管理中设置该服务为自动运行。这样,当在PetShop4程序中异步提交订单时,订单数据就会出现在消息队列的专用队列中了。
订单模块的UI设计
订单的提交界面使用了Wizard控件,以向导的形式创建多个步骤。