Entity Framework: une violation de contrainte d'intégrité référentielle sur une relation plusieurs à plusieurs
Hey j'ai une application avec un tas de cache inproc et entity framework. Quand je veux écrire une mise à jour à une entité, Je rattache la copie mise en cache. Je trace toutes les choses que j'ai attachées dans le cycle de vie du contexte, donc je n'essaie pas de les attacher deux fois.
J'ai une erreur qui se produit sur attach (très rarement dans la plupart des cas cela fonctionne bien et est vraiment rapide) qui dit ce qui suit:
Une violation de contrainte d'intégrité référentielle s'est produite: la propriété valeur qui définissent les contraintes référentielles ne sont pas compatibles entre les objets principaux et dépendants dans la relation.
J'ai regardé très attentivement l'entité qui semble normale. Je pense que ce problème est dû à la pièce jointe/détachement d'une clé étrangère lors des réparations.
Est-il un bon moyen d'obtenir plus d'informations sur cette erreur, ou peut-il se produire pour des raisons autres que l'entité était dans un état qui EF ne m'attendais?
Modifier: Diagramme DB (notez que je suis en utilisant codefirst, je viens d'utiliser L'outil EDMX pour créer le diagramme, j'ai également coupé un tas de propriétés régulières du modèle pour plus de simplicité)
5 réponses
L'erreur peut se produire pour la relation un à plusieurs entre Person
et Location
que vous avez apparemment dans votre modèle en plus de la relation plusieurs à plusieurs. Par exemple, le code suivant lancerait l'exception:
using (var context = new MyContext())
{
var person = new Person
{
CurrentLocationId = 1,
CurrentLocation = new Location { Id = 2 }
};
context.People.Attach(person); // Exception
}
" les valeurs de propriété qui définissent les contraintes référentielles " sont la valeur de propriété de clé étrangère CurrentLocationId
et la valeur de clé primaire CurrentLocation.Id
. Si ces valeurs sont différentes, l'exception est levée. (Avoir CurrentLocation
comme null
est autorisé.)
Dans mon opinion cette exception ne peut être levée que pour les associations de clés étrangères car ce n'est que pour ce type d'association que vous avez des propriétés qui définissent des contraintes référentielles dans votre modèle. Il ne peut pas être jeté pour des associations indépendantes. Puisque chaque relation plusieurs à plusieurs est une association indépendante (pas de propriété de clé étrangère dans le modèle), je suppose que l'erreur n'est pas liée à votre relation plusieurs à plusieurs, mais à la relation un à plusieurs.
Je suis tombé sur une exception très similaire:
"A referential integrity constraint violation occurred:
The property value(s) of 'ObjectA.PropertyX' on one end of a relationship
do not match the property value(s) of 'ObjectB.PropertyY' on the other end."
La raison était la suivante: Le côté client de l'API web a envoyé une requête PUT avec l'objet entier, y compris la propriété de navigation (dans cet exemple ObjectA (plus correctement ObjectB.ObjectA) était une propriété de navigation et a été entièrement fourni par le client). Cela se produit parce que le client reçoit l'objet entier du serveur et le renvoie tel quel vers le serveur avec des modifications mineures.
D'autre part, le ObjectB.PropertyY venait d'être changé (c'était la raison de la demande PUT en premier lieu).
Depuis ObjectB.PropertyY était une référence au même objet ObjectA (une clé étrangère), EF a essayé de concilier cela et a échoué avec l'exception ci-dessus.
La solution était simple:
ObjectB.ObjectA = null;
Avant que SaveChanges() ne résolve complètement cela.
J'espère que cela aide quelqu'un.
Je viens de rencontrer le même problème et la résolution à la mienne était que j'avais ajouté des mappages à l'association, puis configuré les contstraints référentiels.
Afin de résoudre le problème, j'ai dû ouvrir la fenêtre mappages pour l'association et il y avait un lien pour supprimer les mappages. Une fois la fenêtre de détails de mappage terminée, lesdits mappages ne sont pas autorisés.. Il semble que l'ajout de la contrainte référentielle laisse tous les mappages en place.
Pensé qu'il peut être cela vaut la peine d'être publié au cas où quelqu'un d'autre chercherait des solutions à ce message d'erreur à l'avenir.
@ LukeMcGregor Salut,
Je pense que je peux offrir une perspective différente en tant que quelqu'un qui a le même problème.
Après avoir effectué toutes les vérifications nécessaires, je peux dire que je préfère obtenir cette erreur.
Parce que dans mon scénario: je voulais inclure un objet qui a causé une erreur de non-concordance. C'est l'objet de localisation dans votre scénario. Si j'ajoute un objet avec un ID, j'obtiens cette erreur car l'ID de l'objet précédent (celui qui n'est pas mis à jour) ne correspond pas au ID mis à jour.
, Mais ce n'est pas un gros problème. Comme solution; s'il est toujours du côté de L'interface utilisateur, l'objet peut toujours être inclus s'il existe toujours.
Vous viderez l'objet lorsque vous recevrez la demande de mise à jour de l'utilisateur. (=Null) ou vous mettrez à jour l'objet avec L'ID mis à jour par l'utilisateur avant la mise à jour côté service (attach, modified ... peu importe) et le mettre à jour de cette façon.
C'est ça. Il peut rester tel quel dans la base de données et les diagrammes.
J'ai juste eu ce problème et j'ai trouvé une solution assez rapide. Mon problème était avec une table beaucoup-beaucoup.
Public class Pictures_Tag
{
[Key]
[Column(Order = 0)]
[ForeignKey("Picture")]
public Int16 Picture_ID { get; set; }
[Key]
[Column(Order = 1)]
[ForeignKey("ImageTag")]
public Int16 ImageTag_ID { get; set; }
public virtual Picture Picture { get; set; }
public virtual ImageTag ImageTag { get; set; }
}
, j'ai ajouté la ligne où j'ai affecté Picture = db.Pictures...
et puis il a bien fonctionné (pas exactement pourquoi)
[HttpPost]
public ActionResult Edit2(WebSiteEF2017C.Models.Pictures_Tag p)
{
using (var db = new thisModel(Session["org"].ToString())
{
p.Picture = db.Pictures.Where(z => z.ID == p.Picture_ID).FirstOrDefault();
db.Pictures_Tags.Attach(p);
db.Entry(p).State = EntityState.Modified;
db.SaveChanges();
return View(db.Pictures_Tags.Include(x => x.Picture)
.Where(n => n.Picture_ID == p.Picture_ID & n.ImageTag_ID == p.ImageTag_ID).FirstOrDefault());
}
}