如何在ASP.NET MVC 3更新复杂的模型 [英] How to update complex model in ASP.NET MVC 3
问题描述
我试图更新在单个视图一个复杂的模型。
我使用ASP.NET MVC3,实体框架与code首先,工作单位,通用存储库模式..
但是当我尝试更新的模式,我想出了这个错误:
I am trying to update a complex model in a single view. I am using ASP.NET MVC3, Entity Framework with Code first, unit of work, generic repository pattern.. but when I try to update the model, i come up with this error:
参照完整性约束冲突发生:定义引用约束的属性值是不是本金和依赖对象的关系之间是一致的
下面是我的简化视图模型:
Here is my simplified view model:
public class TransactionViewModel
{
public Transaction Transaction { get; set; }
public bool IsUserSubmitting { get; set; }
public IEnumerable<SelectListItem> ContractTypes { get; set; }
}
下面是我的简化复杂的模型,并且作为例子它的导航属性之一。
事务具有其所有导航属性的一对一关系:
Here is my simplified complex model, and as an example one of its navigation property. Transaction has one to one relationship with all of its navigation properties:
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; }
}
使用相同的视图模型,我可以创建一个交易对象,这将填充数据库这样的。
Using the same view model, I am able to create a transaction object, which would populate the database like this.
ID:1,CurrentStageId:1,BidId:1,EvaluationId:1
Id: 1, CurrentStageId: 1, BidId: 1, EvaluationId: 1
但是,当我尝试这些导航属性内更新性能,该行导致错误,在控制器:
but, when I try to update properties within these navigation properties, this line causes the error, in controller:
[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;
}
这个问题进一步复杂化,因为我应该能够在单个视图中编辑任何范围内的任何交易对象中的导航属性的字段(属性)的。
推荐答案
我相信例外含义如下:
定义引用约束的属性值... (这是主键属性(= 编号
)的值出价
键和外键属性(= BidId
)交易价值
)
The property values that define the referential constraints ... (these are the primary key property (= Id
) value of Bid
and the foreign key property (= BidId
) value of Transaction
)
...并不一致...... (=有不同的值)
...委托人之间... (= 出价
)
...和...依赖(= 交易
)
...关系中的对象。
因此,它看起来像下面这样:当MVC模型绑定创建 TransactionViewModel
作为参数的修改
行动 model.Transaction.BidId
和 model.Transaction.Bid.Id
是不同的,例如:
So, it looks like the following: When the MVC model binder creates the TransactionViewModel
as parameter for the Edit
action, model.Transaction.BidId
and model.Transaction.Bid.Id
are different, for example:
-
model.Transaction.BidId.HasValue
是真正
,但model.Transaction.Bid
是空
-
model.Transaction.BidId.HasValue
是假
,但model.Transaction.Bid
不是空
-
model.Transaction.BidId.Value
!=model.Transaction.Bid.Id
model.Transaction.BidId.HasValue
istrue
butmodel.Transaction.Bid
isnull
model.Transaction.BidId.HasValue
isfalse
butmodel.Transaction.Bid
is notnull
model.Transaction.BidId.Value
!=model.Transaction.Bid.Id
(第一点是可能的不的一个问题。我的猜测是,你有情况2)。
(The first point is probably not a problem. My guess is that you have situation 2.)
这同样适用于 CurrentStage
和评估
。
可能的解决方案:
- 设置这些属性相同的值你叫你的资料库中的
更新
方法之前(=黑客) - 绑定
TransactionViewModel.Transaction.BidId
和TransactionViewModel.Transaction.Bid.Id
来两个隐藏形式与领域相同的值,使模型粘合剂填补这两个属性。 - 使用也是一个视图模型为你的内在
交易
属性(以及内部的导航属性交易
以及)这是为您量身定制视图,您可以适当地映射到控制器操作的实体。
- Set those properties to the same values before you call the
Update
method of your repository (=hack) - Bind
TransactionViewModel.Transaction.BidId
andTransactionViewModel.Transaction.Bid.Id
to two hidden form fields with the same value so that the model binder fills both properties. - Use also a ViewModel for your inner
Transaction
property (and for the navigation properties inside ofTransaction
as well) which is tailored to your view and which you can map appropriately to the entities in your controller action.
最后要提的是,这条线......
One last point to mention is that this line ...
context.Entry(entityToUpdate).State = EntityState.Modified;
...没有标志的相关对象( Transaction.Bid
)的修改,所以它不会保存 Transaction.Bid任何变化
。你必须对相关对象的状态设置为修改
以及
... does not flag the related objects (Transaction.Bid
) as modified, so it would not save any changes of Transaction.Bid
. You must set the state for the related objects to Modified
as well.
附注:如果你没有用流利的API,任何额外的映射EF所有的关系不是一比一,但一到多,因为你有单独的FK属性。与EF一到一对一的关系需要共享的主键。
Side note: If you don't have any additional mapping with Fluent API for EF all your relationships are not one-to-one but one-to-many because you have separate FK properties. One-to-One relationships with EF require shared primary keys.
这篇关于如何在ASP.NET MVC 3更新复杂的模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!