我在使用存储库和工作单元模式将对象添加到底层持久性存储(MS SQL Server 2012)时遇到问题。问题是一旦提交,生成的插入语句的顺序就会错误,因此它们会由于外键约束而失败。
想象一下,我们想一次性创建带有订单行的客户、地址、帐户和订单(单次提交):
using (var tx = new TransactionScope())
{
var address = new Address(...);
_addressRepository.Add(address);
var customer = new Customer(...);
customer.AssignLegalAddress(address.Id);
_customerRepository.Add(customer);
var account = new Account(..., customer.Id);
_accountRepository.Add(account);
var order = new Order();
order.AssignBuyerAccount(account.Id);
order.AddOrderLine(...);
order.AddOrderLine(...);
_orderRepository.Add(order);
_unitOfWork.Commit();
tx.Complete();
}
所以为了让客户承诺,地址应该先承诺,客户在账户之前,最后是账户在订单之前。所以我在不同的存储库上调用 Add 的顺序。
上面的存储库首先使用下面的 Entity Framework 5.0 代码,每个添加操作归结为将实体添加到底层 DbContext。我们可以把它翻译成:DbContext.Set<TEntity>().Add(entity)
. 对 Commit 的调用基本上是调用 DbContext.SaveChanges()。
问题是 EF 似乎并不关心它们的添加顺序。在 Commit 上监视发送到底层存储的查询时,我看到首先创建了地址,到目前为止一切都很好,但是随后执行了创建帐户的插入语句。这会失败,因为尚未创建客户。
有没有办法让 EF 在保存更改时考虑我们添加它们的顺序?否则我将不得不手动提交更改,例如:
using (var tx = new TransactionScope())
{
var address = new Address(...);
_addressRepository.Add(address);
_unitOfWork.Commit();
var customer = new Customer(...);
customer.AssignLegalAddress(address.Id);
_customerRepository.Add(customer);
_unitOfWork.Commit();
var account = new Account(..., customer.Id);
_accountRepository.Add(account);
_unitOfWork.Commit();
var order = new Order();
order.AssignBuyerAccount(account.Id);
order.AddOrderLine(...);
order.AddOrderLine(...);
_orderRepository.Add(order);
_unitOfWork.Commit();
tx.Complete();
}
但这似乎不是一个最佳解决方案。有任何想法吗?