4

假设我有一个通用存储库接口,如下所示:

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");
4

6 回答 6

3

在您给出的示例中,我将一步创建Customerand ,并将域对象传递给域对象,而不是传递 Id:Order

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()

...保存更改后,框架会自动填充 和 的 ID ,并Customer根据已分配给.OrderCustomer.IdOrder.customerIdCustomerOrder

于 2011-06-08T10:46:40.367 回答
2

我在客户端(a la CombGuid.NewGuid())上生成 id,然后将其传递给构造函数。使用数据库身份时的方法有严重的缺点

于 2011-06-08T09:38:15.083 回答
1

埃里克,

在您提到的场景中,我没有看到任何 CommitChanges() 正在进行。我会将所有内容包装在事务范围中,然后在添加订单行之前点击 customerRepository.CommitChanges()。然后,您应该能够从新创建的客户对象中获取 id 并按如下方式使用它:

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

然后,如果订单失败,您可以回滚所有内容并通过不点击 scope.Complete() 来保持其原子性。

希望这可以帮助..

于 2011-06-08T09:30:38.293 回答
0

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

在应用存储库模式的域驱动设计中,您不应该将域与数据库联系起来,因此依赖数据库来创建 id 不是一个好主意。

另一点是,您可能希望关联客户,而不仅仅是放置客户 ID,这使得域层变得丰富而稳固。

于 2012-01-05T23:37:00.130 回答
0

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

在调用之后Add,对象的 ID 被设置,然后您可以对该对象进行进一步更改并调用Update,而无需过多了解您的实现。

于 2011-06-08T09:48:49.017 回答
0

根据 DDD,您的界面比存储库更 DAO:

http://codebetter.com/iancooper/2011/04/12/repository-saveupdate-is-a-smell/

就像史蒂夫威尔克斯提到的那样,您应该保持对客户的引用,而不是客户 ID,因此在处理工作单元时,它将在持久性存储(SQL DB、Web 服务等)中创建正确的链接那些实体

有关 DAO 的更多信息:http: //java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html

于 2011-06-09T02:10:41.607 回答