问题描述
我正在使用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;私人集合}
public Order(IOrderNumberGenerator generator){
// ...
}
}
但有一个问题:
可以先保存订单,而不必分配OrderNumber 。所以如果有几天以后,用户想要将订单传递给订单验证者,他将点击请求验证按钮,系统将通过O / R Mapper(我使用NHibernate)从数据库中检索Order对象,注意在这里,我们无法通过IOrderNumberGenerator ,因为Order对象是从O / R Mapper中检索的,所以ORM将通过调用Order类的默认构造函数来重构Order对象(所以我们有没有办法通过IOrderNumberGenerator)。以下是演示代码:
订单订单= repository.GetOrder(orderId);
//生成订单号的代码
xxx.SubmitChanges();
所以我的问题是,如何解决订单号码生成问题,同时仍然保持Order类清洁,
更新:
我现在正在考虑按顺序创建一个名为GenerateOrderNumber()的方法,并通过IOrderNumberGenerator,如下所示:
public class Order {
public void GenerateOrderNumber(IOrderNumberGenerator generator){
_orderNumber = generate.Generate();
}
}
我认为它可以解决问题,但更好解决方案?
BTW:这是我上一个问题的一个扩展问题:
谢谢!
考虑到您要生成 OrderNumber
从代码,并考虑您的笔记:
所以只有当用户点击请求验证按钮
$ b时, $ b
我会说使用 OrderNumberGenerator
在请求验证点击生成订单。
如下所示:
public class OrderNumberGenerator:IOrderNumberGenerator
{
public OrderNumberGenerator(Order order)
{
//为订单参数生成新订单号
}
}
换句话说,在请求时生成一个订单(仅在必要时),并且类型的倒数相似度顺序< ; - > IOrderNumberGenerator
编辑
顺便说一句,考虑到在DB级别上生成OrderNumber,如果可以在你的情况下,像Yahia建议的最可靠的解决方案。
希望这有帮助。
I'm building an ordering system using C# and got a problem on order number generation.
I have an Order class which have an OrderNumber property. I want to make the OrderNumber property readonly, because it's not safe to change OrderNumber.
Because the ordering steps are very complex (4 steps, some steps might take 10 minutes to complete), so I need to save the order in each step. But the client don't want to waste OrderNumber (order numbers are in "Year-Month-An_DB_Value" format), beause the last part of the OrderNumber indicates the order count in that month. So the OrderNumber should be assigned only when the user click "Request Verification" button.
For generating OrderNumber and keep Order class clean(have no dependency to database and can be unit tested), I want to make IOrderNumberGenerator interface as an argument of the constructor of Order class, like this:
public class Order {
public string OrderNumber { get; private set; }
public Order(IOrderNumberGenerator generator) {
// ...
}
}
But there's a problem:
Order can be first saved without having OrderNumber assigned. So if some days later, the user want to pass an Order to the order verifier, he will click the "Request Verification" button, and the system will retrieve the Order object from database via O/R Mapper (I use NHibernate), note that here we have no way to pass the IOrderNumberGenerator, because the Order object is retrieve from O/R Mapper, the ORM will reconstitute the Order object by calling the default constructor of the Order class (so we have no way to pass IOrderNumberGenerator). Here is the demo code:
Order order = repository.GetOrder(orderId);
// code to generate the order number
xxx.SubmitChanges();
So my question is, how to resolve the order number generation problem while still keep the Order class clean and easy to do unit testing.
Updates:I'm now thinking the create a method named GenerateOrderNumber() in order class, and pass the IOrderNumberGenerator, like this:
public class Order {
public void GenerateOrderNumber(IOrderNumberGenerator generator) {
_orderNumber = generate.Generate();
}
}
I think it can resolve the problem, but any better solutions?
BTW: this is an extended question from my last question: Design Decision: OrderNumber property in Order class - Public or Private?
Thanks!
Considering that you want to generate OrderNumber
from code, and considering your note:"So the OrderNumber should be assigned only when the user click "Request Verification" button"
I would say Generate order on "Request Verification" click using OrderNumberGenerator
.
Something like this:
public class OrderNumberGenerator : IOrderNumberGenerator
{
public OrderNumberGenerator(Order order)
{
//generate new order number for order parameter
}
}
In other words, generate an order at the moment of request (only if necessary), and inverse dipendency of types Order<->IOrderNumberGenerator
EDIT
By the way consider also generation of OrderNumber on DB level, if it's possible obviuosly in your case, like Yahia suggested, most reliable solution.
Hope this helps.
这篇关于设计决策:生成依赖于数据库值的OrderNumber的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!