MVC5+EF6下使用UoW模式实现多表关联数据保存的问题咨询
解决方案
方案1:通过EF导航属性自动关联(推荐)
利用Entity Framework的导航属性特性,无需手动处理外键赋值,一次提交即可完成原子写入,避免数据不一致问题。
步骤1:补充实体导航属性
在实体类中添加关联导航属性:
public class Customer { public int Id { get; set; } public string Name { get; set; } // 新增关联导航属性,一个客户对应多条联系信息 public virtual ICollection<ContactDetail> ContactDetails { get; set; } = new List<ContactDetail>(); } // ContactDetail实体可以选择补充导航属性,非强制 public class ContactDetail { public int Id { get; set; } public int CustomerId { get; set; } public int ContactTypeId { get; set; } public string ContactValue { get; set; } public virtual Customer Customer { get; set; } public virtual ContactType ContactType { get; set; } }
步骤2:修改控制器保存逻辑
public ActionResult SaveContactDetails(CustomerContactType viewModel) { // 区分新增客户/编辑已有客户场景 if (viewModel.Customer.Id == 0) { // 新增客户:直接把联系信息加入客户的关联集合 viewModel.Customer.ContactDetails.Add(viewModel.ContactDetail); _unitOfWork.Customers.Add(viewModel.Customer); } else { // 编辑已有客户:先查询到现有客户实例,再追加联系信息 var existCustomer = _unitOfWork.Customers.GetById(viewModel.Customer.Id); existCustomer.ContactDetails.Add(viewModel.ContactDetail); } // 一次保存即可,EF会自动填充ContactDetail的CustomerId字段 _unitOfWork.SaveAllChanges(); return View(); }
方案2:手动控制保存顺序,先存客户取Id再存联系信息
如果不需要调整实体结构,可以手动拆分保存步骤,搭配事务保证数据一致性。
public ActionResult SaveContactDetails(CustomerContactType viewModel) { // 开启事务,避免第二步保存失败产生脏客户数据 using (var transaction = _unitOfWork.BeginTransaction()) { try { // 先保存客户,数据库生成的Id会自动回填到viewModel.Customer.Id _unitOfWork.Customers.Add(viewModel.Customer); _unitOfWork.SaveAllChanges(); // 手动给联系信息赋值CustomerId viewModel.ContactDetail.CustomerId = viewModel.Customer.Id; _unitOfWork.ContactDetails.Add(viewModel.ContactDetail); _unitOfWork.SaveAllChanges(); transaction.Commit(); } catch { transaction.Rollback(); throw; } } return View(); }
注:该方案需要你的UnitOfWork封装了
BeginTransaction方法,可直接调用EF的DbContext.Database.BeginTransaction()实现。
内容的提问来源于stack exchange,提问作者Computer
相关产品推荐
相关产品推荐

