设计决策:生成依赖于数据库值的OrderNumber

时间:2011-10-25 11:09:12

标签: c# .net design-patterns modeling

我正在使用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?

谢谢!

1 个答案:

答案 0 :(得分:0)

考虑到您要从代码生成OrderNumber并考虑您的注意事项: “因此,仅当用户点击”请求验证“按钮”

时才应分配OrderNumber

我会说使用OrderNumberGenerator点击“请求验证”生成订单。

这样的事情:

public class OrderNumberGenerator : IOrderNumberGenerator  
{
   public OrderNumberGenerator(Order  order) 
   {
      //generate new order number for order parameter
   }
}

换句话说,在请求时生成订单(仅在必要时),并且类型的反向相关性Order<->IOrderNumberGenerator

修改

顺便考虑一下在数据库级别生成OrderNumber,如果在你的情况下可能会像Yahia所说的那样显而易见,那就是最可靠的解决方案。

希望这会有所帮助。