6

J'essaie de mettre à jour un modèle complexe dans une vue unique. J'utilise ASP.NET MVC3, Entity Framework avec le code en premier lieu, unité de travail, modèle de référentiel générique .. mais lorsque je tente de mettre à jour le modèle, je viens avec cette erreur:Comment mettre à jour un modèle complexe dans ASP.NET MVC 3

Une contrainte d'intégrité référentielle violation survenue: Les valeurs de propriété qui définissent les contraintes référentielles ne sont pas cohérentes entre les objets principaux et dépendants dans la relation.

Voici mon modèle de vue simplifiée:

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

Voici mon modèle complexe simplifié, et à titre d'exemple un de ses biens de navigation. Transaction a une relation biunivoque avec toutes ses propriétés de navigation:

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

} 

En utilisant le même modèle de vue, je suis en mesure de créer un objet de transaction, qui peupler la base de données comme celui-ci.

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

mais, lorsque je tente de mettre à jour des propriétés au sein de ces propriétés de navigation, cette ligne provoque l'erreur, dans le contrôleur:

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

dans le référentiel générique:

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

Le problème est encore compliqué parce que je devrais être en mesure de modifier l'un des champs (propriétés) dans l'une des propriétés de navigation dans l'objet Transaction dans une vue unique.

Répondre

12

Je crois que l'exception signifie ce qui suit:

Les valeurs des propriétés qui définissent les contraintes référentielles ... (ceux-ci sont la propriété clé primaire (= Id) valeur de Bid et la propriété clé étrangère (= BidId) valeur de Transaction)

... ne sont pas compatibles ... (= ont des valeurs différentes)

... entre principale ... (= Bid)

... et dépendante ... (= Transaction)

... des objets dans la relation.

, il semble donc comme ce qui suit: Lorsque le liant modèle MVC crée le TransactionViewModel comme paramètre pour l'action Edit, model.Transaction.BidId et model.Transaction.Bid.Id sont différents, par exemple:

  • model.Transaction.BidId.HasValue est true mais model.Transaction.Bid est null
  • model.Transaction.BidId.HasValue est false mais model.Transaction.Bid n'est pas null
  • model.Transaction.BidId.Value! = model.Transaction.Bid.Id

(Le premier point est probablement pas un problème. Je suppose que vous avez la situation 2.)

La même chose s'applique à CurrentStage et Evaluation.

solutions possibles:

  • définir ces propriétés aux mêmes valeurs avant d'appeler la méthode Update de votre dépôt (= pirater)
  • Bind TransactionViewModel.Transaction.BidId et TransactionViewModel.Transaction.Bid.Id à deux champs de formulaire cachés avec la même valeur si que le liant modèle remplit les deux propriétés.
  • Utilisez également un ViewModel pour votre propriété interne Transaction (et pour les propriétés de navigation à l'intérieur de Transaction également) adaptée à votre vue et que vous pouvez mapper de manière appropriée aux entités de votre action de contrôleur.

Un dernier point à mentionner est que cette ligne ...

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

... ne signale pas les objets connexes (Transaction.Bid) telle que modifiée, de sorte qu'il ne sauverait pas les changements de Transaction.Bid. Vous devez également définir l'état des objets associés sur Modified. Remarque: Si vous n'avez pas de mappage supplémentaire avec l'API Fluent pour EF, toutes vos relations ne sont pas un à un, mais un à plusieurs, car vous avez des propriétés FK distinctes. Les relations un-à-un avec EF nécessitent des clés primaires partagées.

+1

Vous aviez parfaitement raison! L'utilisation de clés primaires partagées pour une relation un-à-un et la définition manuelle des ID dans le contrôleur ont résolu le problème. Merci! – ljustin

+0

J'ai rencontré un problème similaire où j'avais écrit une classe de référentiel de base générique que tous les autres référentiels pouvaient implémenter. En veillant à ce que seuls les identifiants des entités liées où ils étaient utilisés plutôt que toute l'entité liée résolvent mon problème. – Garry

+0

joonho, im ayant le problème. pouvez-vous aider comment avez-vous défini manuellement les valeurs dans les contrôleurs? – mmssaann

Questions connexes