2012-01-13 68 views
6

我想在單個視圖中更新複雜模型。 我使用ASP.NET MVC3,實體框架與代碼首先,工作單位,通用倉庫模式.. 但是當我嘗試更新的模式,我想出了這個錯誤:如何更新ASP.NET MVC中的複雜模型3

參照完整性約束髮生違規:定義參照約束的屬性值在關係中的主體和從屬對象之間不一致。

這是我的簡化視圖模型:

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

這是我的簡化複雜的模型,並作爲一個例子它的導航屬性之一。 交易與所有的導航屬性的一一對應的關係:

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對象內的任何導航屬性。

回答

12

相信異常指的是下述:

定義參照約束的特性值...(這些是主鍵屬性(= Id)的Bid值和所述外鍵屬性的Transaction(= BidId)值)

...不一致...(=具有不同的值)

...委託人之間...(= Bid

...和從屬...(= Transaction

在各關係的對象。

因此,它看起來像下面這樣:當MVC模型綁定的參數爲Edit行動創建TransactionViewModelmodel.Transaction.BidIdmodel.Transaction.Bid.Id是不同的,例如:

  • model.Transaction.BidId.HasValuetruemodel.Transaction.Bidnull
  • model.Transaction.BidId.HasValuefalsemodel.Transaction.Bid不是null
  • model.Transaction.BidId.Value!= model.Transaction.Bid.Id

(第一點是可能問題。我的猜測是你有情況2.)

這同樣適用於CurrentStageEvaluation

可能的解決方案:

  • 設置這些屬性相同的價值觀,你打電話給你的資料庫的Update方法之前(=黑客)
  • 綁定TransactionViewModel.Transaction.BidIdTransactionViewModel.Transaction.Bid.Id具有相同值的兩個隱藏的表單字段,以便模型聯編程序填充了這兩個屬性。
  • 也可以爲您的內部Transaction屬性(以及Transaction內部的導航屬性)使用視圖模型,該視圖適合您的視圖,並且您可以將其適當地映射到控制器操作中的實體。

最後要提的是,這條線......

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

...不會標記爲已修改,所以它不會保存Transaction.Bid任何變化相關對象(Transaction.Bid)。您必須設置狀態相關的對象,以Modified爲好。

邊注:如果你沒有用流利的API,任何額外的映射EF所有關係都沒有一個對一個,但一到多,因爲你必須單獨FK性能。與EF的一對一關係需要共享主鍵。

+1

你是完全正確!使用共享主鍵爲一比一的關係和手動設置在控制器的ID解決了這個問題。謝謝! – ljustin 2012-01-25 14:05:19

+0

我正在經歷我在那裏寫了所有其他存儲庫可以實現一個通用基倉儲類有類似的問題。通過確保只有使用相關實體的ID而不是整個相關實體解決了我的問題。 – Garry 2012-12-05 19:32:45

+0

joonho,遇到的問題IM。你能幫助你如何在控制器中手動設置數值嗎? – mmssaann 2013-06-14 07:06:43