2012-01-13 16 views
6

Próbuję zaktualizować złożony model w jednym widoku. Używam ASP.NET MVC3, Entity Framework z Kodeksem pierwszy jednostce pracy, rodzajowy repozytorium wzór .. ale przy próbie aktualizacji modelu, i wymyślić ten błąd:Jak zaktualizować złożony model w środowisku ASP.NET MVC 3

więzów integralności więzów naruszenie wystąpiło: wartości właściwości, które definiują ograniczenia referencyjne, nie są spójne między obiektami głównymi i zależnymi w relacji.

Oto mój model uproszczony widok:

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

Oto moje uproszczone złożony model, a jako przykład jednej z jego właściwości nawigacji. transakcja ma jeden do jeden związek ze wszystkimi jego właściwościami nawigacja:

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; } 

} 

użyciu tego samego modelu widoku, jestem w stanie stworzyć przedmiot transakcji, które mogłyby wypełnić bazę takiego.

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

ale gdy próbuję zaktualizować właściwości w ciągu tych właściwości nawigacyjnych, linia ta powoduje błąd w sterowniku:

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

w ogólnych repozytorium

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

problem staje się ponadto skomplikowane, ponieważ powinny być w stanie zmienić każdy z obszarów (właściwości) w dowolną właściwość nawigacji w obiekcie Transaction w jednym widoku.

Odpowiedz

12

wierzę, że wyjątek oznacza:

wartości właściwości, które definiują ograniczenia referencyjne ... (są własnością klucz podstawowy (= Id) wartości Bid a właściwość klucza obcego (= BidId) wartość Transaction)

... nie są zgodne ... (= mają różne wartości)

... między osobą ... (= Bid)

... i zależne ... (= Transaction)

... obiektów w związku.

Tak, to wygląda następująco: Kiedy spoiwo modelu MVC tworzy TransactionViewModel jako parametr dla działania Edit, model.Transaction.BidId i model.Transaction.Bid.Id są różne, na przykład:

  • model.Transaction.BidId.HasValue jest true ale model.Transaction.Bid jest null
  • model.Transaction.BidId.HasValue jest false ale model.Transaction.Bid nie jest null
  • model.Transaction.BidId.Value! = model.Transaction.Bid.Id

(Pierwszy punkt jest prawdopodobnie nie problem. Zgaduję, że masz sytuację 2.)

To samo dotyczy CurrentStage i Evaluation.

Możliwe rozwiązania:

  • ustawić te właściwości do tych samych wartości, przed wywołaniem metody repozytorium Update (= siekać)
  • Bind TransactionViewModel.Transaction.BidId i TransactionViewModel.Transaction.Bid.Id do dwóch ukrytych pól formularza o tej samej wartości, tak że model spoiwa wypełnia obie właściwości.
  • Użyj również ViewModel dla swojej wewnętrznej właściwości Transaction (i dla właściwości nawigacji wewnątrz Transaction), która jest dostosowana do twojego widoku i którą możesz odpowiednio odwzorować na obiekty w akcji kontrolera.

Ostatni punkt wspomnieć, że ta linia ...

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

... nie flaga powiązane obiekty (Transaction.Bid), zmieniony, więc nie byłoby zapisać zmiany Transaction.Bid. Musisz także ustawić stan powiązanych obiektów na Modified.

Uwaga: Jeśli nie masz żadnego dodatkowego odwzorowania w Fluent API for EF, wszystkie twoje relacje nie są jeden do jednego, ale jeden do wielu, ponieważ masz oddzielne właściwości FK. Relacje jeden-do-jednego z EF wymagają wspólnych kluczy podstawowych.

+1

Masz dokładnie rację! Używanie wspólnych kluczy podstawowych do relacji jeden-do-jednego i ręczne ustawianie identyfikatorów w kontrolerze rozwiązało problem. Dzięki! – ljustin

+0

Wystąpił podobny problem, gdy napisałem ogólną bazę klasy repozytorium, którą wszystkie inne repozytoria mogłyby zaimplementować. Upewniając się, że tylko identyfikatory powiązanych podmiotów, które są używane, a nie cały powiązany podmiot rozwiązały mój problem. – Garry

+0

joonho, mam problem. możesz pomóc, w jaki sposób ustawiłeś wartości ręcznie w kontrolerze? – mmssaann