2011-06-08 49 views
3

说我有一个通用的库接口如下:如何确定添加到存储库的聚合根的标识号?

public interface IRepository<T> 
{ 
    Add(T item); 
    Delete(int itemId); 
    Update(T item); 
} 

通常通过IRepository.Add(添加的物品的)新的ID会被一些后端数据库来确定,但只有一次整体交易/工作单位已提交。所以我很确定IRepository.Add()返回添加项的新ID是错误的。存储库真的不应该知道如何创建ID。它是否正确?

如果这是一种情况,如何确定添加到存储库的项目的新ID,还是应该这样做?我知道像NHibernate这样的ORM能够用正确的ID自动地用新对象替换内存中的对象,但是我试图设计我的仓库时没有考虑到任何特定的ORM实现。

例如说我有一个网站,客户可以下订单。新客户选择退房并发送至表单以填写详细信息。该信息用于创建存储在CustomerRepository中的Customer对象。现在他们的订单信息需要被创建,但是订单需要通过他们的ID来引用客户?

Customer newCustomer = new Customer(first, last, address, phone dateOfBirth); 
customerRepository.Add(newCustomer); 

//How would I determine customerId?? 
Order newOrder = new Order(customerId, shippingAddress, billingAddress); 
newOrder.AddOrderItem("widget"); 
newOrder.AddOrderItem("doohicky"); 
newOrder.AddOrderItem("stuff"); 

回答

1

埃里克,

在你所提到的情况下,我没有看到任何的CommitChanges()怎么回事。我会将所有内容都包含在一个transactionscope中,然后在添加命令行之前打上customerRepository.CommitChanges()。那么你应该能够从新创建的客户对象抢ID和按如下方式使用它:

Order newOrder = new Order(newCustomer.Id, shippingAddress, billingAddress); 

那么,如果订单(S)失败了,你可以滚一切恢复并保持它的原子通过不打scope.Complete()。

希望这有助于..

+0

在我看到的例子中,存储库并不像您所描述的那样提交更改。而是每个存储库引用一个可以提交或回滚的UnitOfWork对象。不过,我的印象是,UnitOfWork对象通常是安装的,因此它只能回滚尚未提交的更改。 – 2011-06-08 23:16:55

0

无论您是否使用NHibernate,我都觉得它采用的方法是正确的。任何域对象的目标是在任何时候只在内存中拥有该对象的一个​​实例,即不应该有两个代表相同数据库记录的对象。因此,如果数据库用新的id更新记录,则内存中的域对象也应该用该ID更新,因为那是该记录的“真实”表示。

调用Add后,对象的ID被设置,然后您可以对该对象进行进一步更改并调用Update,而无需知道太多关于您的实现。

+0

因此,应该假定IRepository.Add()的任何特定实现将设置要添加的项目的ID? – 2011-06-08 22:44:11

+0

我认为这是一个很好的方法。 – 2011-06-09 09:02:27

3

在你给的例子,我想创建一个步骤CustomerOrder,和域对象传递,而不是通过IDS域对象,:

Customer newCustomer = new Customer(first, last, address, phone dateOfBirth); 

// Pass the customer rather than the CustomerId: 
Order newOrder = new Order(newCustomer , shippingAddress, billingAddress); 
newOrder.AddOrderItem("widget"); 
newOrder.AddOrderItem("doohicky"); 
newOrder.AddOrderItem("stuff"); 

customerRepository.Add(newCustomer); 
orderRepository.Add(newOrder); 

// SaveChanges() 

...当保存更改,该框架自动填充CustomerOrder两者的ID,并且凭借已被分配给OrderCustomer对象填充Customer.Id,Order.customerId(等)。

0

域实体应该有THEI r自己的ID战略,无论数据库ID,所以最好在域层生成你的ID,或者如果你真的需要在数据库中生成ID,那么在数据库自动生成的ID旁边的域层添加另一个域标识符。

在应用存储库模式的域驱动设计中,您不应该将域与数据库绑定,因此依靠数据库创建ID不是一个好主意。

另一点是,您可能想要使客户关联,以便不仅放置客户ID,这使得领域层丰富而扎实。