1

我在使用存储库和工作单元模式将对象添加到底层持久性存储(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();
}

但这似乎不是一个最佳解决方案。有任何想法吗?

4

1 回答 1

0

如果要插入实体,则 EF 将插入整个图。

// Build graph
var customer = new Customer(...);
customer.LegalAddress = new Address(...);
var account = new Account();
account.Customer = customer;
var order = new Order();
order.BuyerAccount = account;
// Here all Navigation properties updated
// and state of all entities set to Added
_orderRepository.Add(order); 
// Here all entities inserted in transaction, PK and FK updated
context.SaveChanges();

当您只需要插入图形的一部分时,复杂性就开始了。然后你应该手动设置图中实体的状态。

于 2013-03-20T09:36:06.547 回答