asp.net-mvc – 如何在ASP.NET MVC 3中更新复杂模型

我试图在单个视图中更新复杂模型.
我正在使用ASP.NET MVC3,Entity Framework with Code first,工作单元,通用存储库模式..
但是当我尝试更新模型时,我想出了这个错误:

发生了引用完整性约束违规:定义引用约束的属性值在关系中的主体和从属对象之间不一致.

这是我的简化视图模型:

public class TransactionViewModel
{
     public Transaction Transaction { get; set; }
     public bool IsUserSubmitting { get; set; }
     public IEnumerable<SelectListItem> ContractTypes { get; set; }
}

这是我的简化复杂模型,并作为其导航属性之一的示例.
Transaction与其所有导航属性具有一对一的关系:

public class Transaction
{
    [Key]
    public int Id { get; set; }

    public int CurrentStageId { get; set; }

    public int? BidId { get; set; }

    public int? EvaluationId { get; set; }

    public virtual Stage CurrentStage { get; set; }

    public virtual Bid Bid { get; set; }

    public virtual Evaluation Evaluation { get; set; }

}

public class Bid
{
    [Key]
    public int Id { get; set; }

    public string Type { get; set; }

    public DateTime? PublicationDate { get; set; }

    public DateTime? BidOpeningDate { get; set; }

    public DateTime? ServiceDate { get; set; }

    public string ContractBuyerComments { get; set; }

    public string BidNumber { get; set; }

    public DateTime? ReminderDate { get; set; }

    public DateTime? SubmitDate { get; set; }

}

使用相同的视图模型,我能够创建一个事务对象,它将像这样填充数据库.

Id:1,CurrentStageId:1,BidId:1,EvaluationId:1

但是,当我尝试更新这些导航属性中的属性时,此行会在控制器中导致错误:

[HttpPost]
public ActionResult Edit(TransactionViewModel model)
{
    if (ModelState.IsValid)
    {
        -> unitOfWork.TransactionRepository.Update(model.Transaction);
           unitOfWork.Save();
           return RedirectToAction("List");
    }
}

在通用存储库中:

public virtual void Update(TEntity entityToUpdate)
{
 -> dbSet.Attach(entityToUpdate);
    context.Entry(entityToUpdate).State = EntityState.Modified;
}

问题更加复杂,因为我应该能够在单个视图中编辑Transaction对象中任何导航属性中的任何字段(属性).

解决方法

我相信例外意味着以下内容:

定义引用约束的属性值…(这些是Bid的主键属性(= Id)值和Transaction的外键属性(= BidId)值)

……不一致……(=有不同的值)

……校长之间…(=投标)

……和依赖…(=交易)

……关系中的对象.

因此,它看起来如下所示:当MVC模型绑定器创建TransactionViewModel作为Edit操作的参数时,model.Transaction.BidId和model.Transaction.Bid.Id是不同的,例如:

> model.Transaction.BidId.HasValue为true但model.Transaction.Bid为null
> model.Transaction.BidId.HasValue为false但model.Transaction.Bid不为null
> model.Transaction.BidId.Value!= model.Transaction.Bid.Id

(第一点可能不是问题.我的猜测是你有情况2.)

这同样适用于CurrentStage和Evaluation.

可能的解决方案:

>在调用存储库的Update方法之前,将这些属性设置为相同的值(= hack)
>将TransactionViewModel.Transaction.BidId和TransactionViewModel.Transaction.Bid.Id绑定到具有相同值的两个隐藏表单字段,以便模型绑定器填充这两个属性.
>还可以使用ViewModel作为内部Transaction属性(以及Transaction内部的导航属性),该属性是根据您的视图定制的,您可以将其适当地映射到控制器操作中的实体.

最后一点要提到的是这条线……

context.Entry(entityToUpdate).State = EntityState.Modified;

…不会将相关对象(Transaction.Bid)标记为已修改,因此不会保存Transaction.Bid的任何更改.您还必须将相关对象的状态设置为“已修改”.

附注:如果您没有使用Fluent API for EF的任何其他映射,那么您的所有关系不是一对一的,而是一对多的,因为您有单独的FK属性.与EF的一对一关系需要共享主键.

相关文章

引言 本文从Linux小白的视角, 在CentOS 7.x服务器上搭建一个...
引言: 多线程编程/异步编程非常复杂,有很多概念和工具需要...
一. 宏观概念 ASP.NET Core Middleware是在应用程序处理管道...
背景 在.Net和C#中运行异步代码相当简单,因为我们有时候需要...
HTTP基本认证 在HTTP中,HTTP基本认证(Basic Authenticatio...
1.Linq 执行多列排序 OrderBy的意义是按照指定顺序排序,连续...