我正在使用C#构建订购系统,并且在订单号生成方面遇到了问题。
我有一个Order类,它有一个OrderNumber属性。我想只读取OrderNumber属性,因为更改OrderNumber是不安全的。
由于订购步骤非常复杂(4个步骤,某些步骤可能需要10分钟才能完成),因此我需要在每个步骤中保存订单。但是客户端不想浪费OrderNumber(订单号以“Year-Month-An_DB_Value”格式),因为OrderNumber的最后一部分表示该月的订单数量。因此,仅当用户单击“请求验证”按钮时才应分配OrderNumber。
为了生成OrderNumber并保持Order类干净(不依赖于数据库并且可以进行单元测试),我想将IOrderNumberGenerator接口作为Order类构造函数的参数,如下所示:
public class Order {
public string OrderNumber { get; private set; }
public Order(IOrderNumberGenerator generator) {
// ...
}
}
但是有一个问题:
可以在未分配OrderNumber的情况下首先保存订单。因此,如果几天后,用户想要将订单传递给订单验证程序,他将单击“请求验证”按钮,系统将通过O / R Mapper从我的数据库中检索Order对象(我使用NHibernate),注意这里我们无法传递IOrderNumberGenerator ,因为Order对象是从O / R Mapper中检索的,ORM将通过调用Order类的默认构造函数来重构Order对象(所以我们有无法通过IOrderNumberGenerator)。这是演示代码:
Order order = repository.GetOrder(orderId);
// code to generate the order number
xxx.SubmitChanges();
所以我的问题是,如何在保持Order类干净且易于进行单元测试的同时解决订单号生成问题。
更新 我现在正在考虑在顺序类中创建一个名为GenerateOrderNumber()的方法,并传递IOrderNumberGenerator,如下所示:
public class Order {
public void GenerateOrderNumber(IOrderNumberGenerator generator) {
_orderNumber = generate.Generate();
}
}
我认为它可以解决问题,但有更好的解决方案吗?
BTW:这是我上一期提问的一个扩展问题:Design Decision: OrderNumber property in Order class - Public or Private?
谢谢!
答案 0 :(得分:0)
考虑到您要从代码生成OrderNumber
并考虑您的注意事项:
“因此,仅当用户点击”请求验证“按钮”
我会说使用OrderNumberGenerator
点击“请求验证”生成订单。
这样的事情:
public class OrderNumberGenerator : IOrderNumberGenerator
{
public OrderNumberGenerator(Order order)
{
//generate new order number for order parameter
}
}
换句话说,在请求时生成订单(仅在必要时),并且类型的反向相关性Order<->IOrderNumberGenerator
修改强>
顺便考虑一下在数据库级别生成OrderNumber,如果在你的情况下可能会像Yahia所说的那样显而易见,那就是最可靠的解决方案。
希望这会有所帮助。