2012-01-13 22 views
6

Sto tentando di aggiornare un modello complesso in una singola vista. Sto usando ASP.NET MVC3, Entity Framework con il codice prima, unità di lavoro, modello repository generico .. ma quando provo ad aggiornare il modello, vengo con questo errore:Come aggiornare il modello complesso in ASP.NET MVC 3

Un vincolo di integrità referenziale violazione verificatasi: i valori delle proprietà che definiscono i vincoli referenziali non sono coerenti tra gli oggetti principale e dipendente nella relazione.

Ecco il mio semplificato modello di vista:

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

Ecco il mio modello complesso semplificato, e come esempio uno dei suoi proprietà di navigazione. transazione ha relazione uno a uno con tutte le sue proprietà di navigazione:

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

} 

Utilizzando lo stesso modello di vista, sono in grado di creare un oggetto di transazione, che avrebbe popolare il database come questo.

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

ma, quando provo ad aggiornare le proprietà all'interno di queste proprietà di navigazione, questa linea causa l'errore, nel regolatore:

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

In repository generico:

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

Il problema è ulteriormente complicato perché dovrei essere in grado di modificare uno qualsiasi dei campi (proprietà) all'interno qualsiasi proprietà di navigazione nell'oggetto Transaction all'interno di una singola vista.

risposta

12

ritengo che l'eccezione significa quanto segue:

I valori di proprietà che definiscono i vincoli di riferimento ... (questi sono di proprietà chiave primaria (= Id) valore Bid e la proprietà chiave esterna (= BidId) valore Transaction)

... non sono coerenti ... (= sono valori diversi)

... tra principal ... (= Bid)

... e dipendente ... (= Transaction)

... oggetti nel rapporto.

Così, sembra che il seguente: Quando il modello MVC legante crea il TransactionViewModel come parametro per l'azione Edit, model.Transaction.BidId e model.Transaction.Bid.Id sono diversi, ad esempio:

  • model.Transaction.BidId.HasValue è true ma model.Transaction.Bid è null
  • model.Transaction.BidId.HasValue è false ma model.Transaction.Bid non è null
  • model.Transaction.BidId.Value! = model.Transaction.Bid.Id

(Il primo punto è probabilmente non un problema. La mia ipotesi è che tu abbia la situazione 2.)

Lo stesso vale per CurrentStage e Evaluation.

Possibili soluzioni:

  • impostare tali proprietà agli stessi valori prima di chiamare il metodo del repository Update (= hack)
  • Bind TransactionViewModel.Transaction.BidId e TransactionViewModel.Transaction.Bid.Id a due campi di modulo nascosto con lo stesso valore in modo che il raccoglitore modello riempie entrambe le proprietà.
  • Usa anche un ViewModel per la tua proprietà interna Transaction (e anche per le proprietà di navigazione all'interno di Transaction) che è adattata alla tua vista e che puoi mappare in modo appropriato alle entità nell'azione del tuo controller.

Un ultimo punto da ricordare è che questa linea ...

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

... non contrassegna gli oggetti correlati (Transaction.Bid) come modificato, quindi non sarebbe salvare le modifiche di Transaction.Bid. È necessario impostare lo stato degli oggetti correlati su Modified.

Nota a margine: se non si dispone di alcuna mappatura aggiuntiva con Fluent API for EF tutte le relazioni non sono one-to-one ma one-to-many perché si hanno proprietà FK separate. Le relazioni one-to-one con EF richiedono chiavi primarie condivise.

+1

Avevi esattamente ragione! L'utilizzo di chiavi primarie condivise per la relazione uno a uno e l'impostazione manuale degli ID nel controller ha risolto il problema. Grazie! – ljustin

+0

Ho riscontrato un problema simile in cui avevo scritto una classe di repository di base generica che tutti gli altri repository potevano implementare. Garantendo che solo gli ID delle entità correlate dove sono stati utilizzati piuttosto che l'intera entità correlata hanno risolto il mio problema. – Garry

+0

joonho, sto avendo il problema. puoi aiutarmi come hai impostato manualmente i valori in controller pls? – mmssaann

Problemi correlati