You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.09 00:27:01