一次在多个表中插入/更新数据的最佳实践

时间:2011-02-11 03:12:22

标签: c# asp.net asp.net-mvc

所以我的数据库中有两个表,联系人和地址:

通讯录:ContactID |地址ID | FirstName |名字

地址:地址ID |地址1 |地址2 |城市|国家|邮政编码

我有一个页面,您可以在其中添加联系人。它包含联系人的所有信息和联系人的地址。这是我提交表单时的代码:

[HttpPost]
public ActionResult Edit(ContactsViewModel viewModel)
{
    //if editing an contact, fetch it; otherwise, create a new one
    Contact contact = viewModel.ContactId == 0
        ? new Contact()
        : _adminRepository.GetContact(viewModel.ContactId);
    TryUpdateModel(contact);

    if (ModelState.IsValid)
    {
        _adminRepository.SaveAddress(contact.Address);
        _adminRepository.SaveContact(contact);

        return RedirectToAction("Index");
    }
    return View(viewModel);     // validation error, so redisplay same view
}

现在我主要担心的是地址添加成功,但是当我尝试保存联系人时会发生错误,而地址在数据库中没有联系。

如果发生错误,回滚任何更改的最佳做法是什么?

4 个答案:

答案 0 :(得分:4)

那应该是一种方法,而不是两种

如果地址始终与联系人相关(似乎就是这样),那么您应该只有一个存储库 - 例如 ContactRepository

每个聚合根应该有一个存储库,或者简单来说 - 每个实体的存储库都需要自己检索。

我不知道_adminRepository是什么,但我认为你只是拥有SaveContact(contact)方法。

您是否正在使用类似于Entity Framework的ORM?如果是这样,两个插入都将在一个事务中完成(由EF处理),因此如果一个失败,两个都将失败。

如果您开始针对多个存储库/聚合根进行更改,那么您将需要类似工作单元 TransactionScope。

所以听起来你需要重新考虑一下你的存储库设计。对于单个聚合实体(联系人)应该有一个通用的保存方法,而不是每个关系的单独聚合实体。

答案 1 :(得分:1)

“工作单元”模式很好,也可以接受多种操作的解决方案 - 对于db -or anothers操作也是如此 - 请阅读Faisal Mohamood, Program Manager, Entity Framework blogs.中的样本

答案 2 :(得分:0)

您需要在存储库中使用TransactionScope()。查看MSDN forum entry。第一个回复显示了将其集成到方法中的简单示例。关键是如果没有它,就没有办法专门回滚更改。

答案 3 :(得分:0)

我的偏好是使一个存储过程插入两个记录。您可以使用TSQL事务。使用TransactionScope()也可以工作,因此决策应该基于您的数据访问层。如果您已经使用了很多SPROC,请使用事务进行复杂的SPROC。

如果您正在使用Entity Framework(......痛苦!!!!),那么.net TransactionScope()会更好。