Entity Framework: Eine Verletzung der referenziellen Integritätsbedingung für viele zu viele Beziehungen

Hey, ich habe eine Anwendung mit ein paar Inproc-Caching- und Entity-Frameworks. Wenn ich ein Update für eine Entität schreiben möchte, füge ich die zwischengespeicherte Kopie erneut hinzu. Ich verfolge alle Dinge, die ich im Lebenszyklus des Kontexts angehängt habe, damit ich nicht versuche, sie zweimal anzuhängen.

Ich habe einen Fehler beim Anhängen (sehr selten in den meisten Fällen funktioniert dies gut und ist sehr schnell), der Folgendes besagt:

Es ist eine Verletzung der referenziellen Integritätsbedingungen aufgetreten: Die Eigenschaftswerte, die die referenziellen Bedingungen definieren, sind zwischen Haupt- und abhängigen Objekten in der Beziehung nicht konsistent.

Ich habe mir die Entität, die normal aussieht, sehr genau angesehen. Ich denke, dass dieses Problem auf das Anhängen / Entfernen eines Fremdschlüssels zurückzuführen ist, wenn Fixups ausgeführt werden.

Gibt es eine gute Möglichkeit, weitere Informationen zu diesem Fehler abzurufen, oder kann dies auch aus anderen Gründen auftreten, als wenn sich die Entität in einem Zustand befunden hat, den EF nicht erwartet hat?

BEARBEITEN: DB-Diagramm (Anmerkung: Ich verwende Codefirst. Ich habe gerade das EDMX-Tool verwendet, um das Diagramm zu erstellen. Der Einfachheit halber habe ich auch einige reguläre Eigenschaften aus dem Modell herausgeschnitten.)

 Luke McGregor03. Apr. 2012, 23:04
Ich benutze CodeFirst, mein Modell ist wirklich einfach, ich poste ein Diagramm in einer Sekunde
 NSGaga04. Apr. 2012, 23:28
Luke, können Sie den CF-Teil angeben, wie ordnen Sie die Dinge zu - wie sehen Ihre Modellklassen aus, Ihr Migrationscode? Um jedem dabei helfen zu können.
 NSGaga03. Apr. 2012, 22:59
Verwenden Sie zuerst Code oder zuerst ein Modell - und weitere Informationen zu Ihrem Modell, zu Tabellen / Klassen, die sich auf den Fehler beziehen, und zur Zuordnung von vielen zu vielen. Wenn Sie zuerst Code verwenden, bevorzuge ich es, die Relation 'manuell' auszuführen, damit ich alle Aspekte kontrollieren und ähnliche Dinge vermeiden kann. Auf der anderen Seite bedeutet ein Fehler in Bezug auf die referenzielle Integrität wahrscheinlich genau das - ich glaube nicht, dass dies der Zustand des Objekts ist, obwohl er sich meiner Meinung nach auf ähnliche Weise manifestieren könnte.

Antworten auf die Frage(6)

Lösung für das Problem

Der Fehler kann bei der Eins-zu-Viele-Beziehung zwischen auftretenPerson undLocation Sie haben anscheinend in Ihrem Modell zusätzlich zu den vielen-zu-vielen-Beziehungen. Der folgende Code würde beispielsweise die Ausnahme auslösen:

<code>using (var context = new MyContext())
{
    var person = new Person
    {
        CurrentLocationId = 1,
        CurrentLocation = new Location { Id = 2 }
    };
    context.People.Attach(person); // Exception
}
</code>

"Die Eigenschaftswerte, die die referenziellen Einschränkungen definieren", sind die FremdschlüsseleigenschaftswerteCurrentLocationId und der PrimärschlüsselwertCurrentLocation.Id. Wenn diese Werte unterschiedlich sind, wird die Ausnahme ausgelöst. (MitCurrentLocation wienull ist aber erlaubt.)

Meiner Meinung nach kann diese Ausnahme nur für Fremdschlüsselzuordnungen ausgelöst werden, da Sie nur für diese Zuordnungsart Eigenschaften haben, die in Ihrem Modell überhaupt referenzielle Einschränkungen definieren. Es kann nicht für unabhängige Vereinigungen geworfen werden. Da jede Viele-zu-Viele-Beziehung eine unabhängige Assoziation ist (keine Fremdschlüsseleigenschaft im Modell), gehe ich davon aus, dass der Fehler nicht mit Ihrer Viele-zu-Viele-Beziehung zusammenhängt, sondern mit der Eins-zu-Viele-Beziehung.

 Shimmy08. Juni 2013, 23:37
Wie stelle ich das ein?Locations zumPersons (angesichts derLocations IDs)? In meinem Szenario ist es ein viel zu viel Problem. Was ist die allgemeine Lösung für diese Ausnahme, wie komme ich darum herum?
 Slauma09. Juni 2013, 01:38
@Shimmy: Das ist, was Anhängen (context.Categories.Attach(category)) ist für: EF mitteilen, dass die Kategorien bereits existieren.
 Slauma09. Juni 2013, 00:00
@Shimmy: Setzen Sie entweder die FK-Eigenschaft und lassen Sie die Navigationseigenschaft unverändertnull (was ich in diesem Fall tun würde) oder sicherstellen, dass der FK-Eigenschaftswert und der PK-Wert der Entität, die auf die Navigationseigenschaft festgelegt sind, identisch sind. Nach meinem Verständnis kann diese Ausnahme jedoch nicht für viele-zu-viele-Beziehungen auftreten. Es ist eine Ausnahme, die sich nur auf FK-Assoziationen bezieht, und viele-zu-viele-Beziehungen sind unabhängige Assoziationen, keine FK-Assoziationen.
 Shimmy09. Juni 2013, 00:24
In meinem Szenario habe ichCategorys undBusiness. Jedes Unternehmen kann mehrere habenCategorys. Ich habe eine Liste der Kategorie-IDs, die ich anhängen möchte. Wie mache ich das?
 Shimmy09. Juni 2013, 01:19
Sie erinnern sich, dass alle Kategorien in der Datenbank bereits vorhanden sind, bevor die zugehörigen PKs den einzelnen Unternehmen zugeordnet werden. Ist das richtig?
 Slauma09. Juni 2013, 01:14
@Shimmy: Stub-Kategorien erstellen (new Category { Id = id }), hängen Sie sie an den Kontext an und fügen Sie sie dem Kontext hinzuBusiness.Categories Änderungen erfassen und speichern. Dies scheint jedoch ein wenig von dieser Frage und Antwort abzuweichen. Erstellen Sie möglicherweise eine neue Frage, um gezieltere Antworten zu erhalten.
 Shimmy09. Juni 2013, 01:39

müssen Sie Ihrem Kontext nicht nur Objekte hinzufügen. Wenn Sie beispielsweise die CurrentLocationId in Person bearbeiten, müssen Sie auch das in das Person-Objekt eingebettete CurrentLocation-Objekt bearbeiten. EF füllt das CurrentLocation-Objekt automatisch mit Daten, da CurrentLocationId einen Fremdschlüssel in der CurrentLocation-Tabelle enthält. Wenn Sie die CurrentLocationId bearbeiten, ohne auch das CurrentLocation-Objekt zu aktualisieren, sind sie nicht mehr synchron. Dies ist der Grund für die Ausnahme in diesem Fall.

Angenommen, Sie mussten die CurrentLocationId des Personenobjekts aktualisieren. Wir gehen davon aus, dass Sie die Personendaten und die Standortdaten vorab abgerufen haben.

<code>public class DbData 
{
    List<Person> PersonList;
    List<Location> LocationList;
    public DbData()
    {
        using (var context = new MyContext())
        {
             PersonList = context.Persons.ToList();
             LocationList = context.Locations.ToList();
        }
    }

    public void UpdatePersonLocation(Person person, int newLocationId)
    {
        using (var context = new MyContext())
        {
            var location = LocationList.Where(l=>l.id==newLocationId).Single();
            //you need to update both the id and the location for this to not throw the exception
            person.CurrentLocationId == newLocationId;
            person.CurrentLocation == location;  
            context.Entry(person).State = System.Data.Entity.EntityState.Modified;
            context.SaveChanges();
        }
    }
    //or if you're giving it the location object...
    public void UpdatePersonLocation(Person person, Location location)
    {
        using (var context = new MyContext())
        {
            //you need to update both the id and the location for this to not throw the exception
            person.CurrentLocationId == location.id;
            person.CurrentLocation == location;  
            context.Entry(person).State = System.Data.Entity.EntityState.Modified;
            context.SaveChanges();
        }
    }
}
</code>

Ich denke, ich kann eine andere Perspektive bieten als jemand, der das gleiche Problem hat.

Nachdem ich alle notwendigen Überprüfungen durchgeführt habe, kann ich sagen, dass ich diesen Fehler lieber bekomme.

Denn in meinem Szenario: Ich wollte ein Objekt einfügen, das einen Nichtübereinstimmungsfehler verursacht hat. Es ist das Standortobjekt in Ihrem Szenario. Wenn ich ein Objekt mit einer ID hinzufüge, wird dieser Fehler angezeigt, da die ID im vorherigen Objekt (das nicht aktualisiert wurde) nicht mit der aktualisierten ID übereinstimmt.

Aber es ist kein großes Problem. Als Lösung; Befindet sich das Objekt noch auf der Seite der Benutzeroberfläche, wird es möglicherweise noch einbezogen, sofern es noch vorhanden ist.

Sie werden das Objekt entweder leeren, wenn Sie die Aktualisierungsanforderung vom Benutzer erhalten. (= Null) Oder Sie aktualisieren das Objekt mit der vom Benutzer aktualisierten ID vor dem service-seitigen Update (anhängen, modifizieren ... was auch immer) und aktualisieren es auf diese Weise.

Das ist es. Es kann so bleiben, wie es in der Datenbank und in den Diagrammen ist.

Ich bin auf eine sehr ähnliche Ausnahme gestoßen:

<code>"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."
</code>

Der Grund war folgender: Die Clientseite der Web-API hat eine PUT-Anforderung mit dem gesamten Objekt einschließlich der Navigationseigenschaft gesendet (in diesem Beispiel war ObjectA (genauer ObjectB.ObjectA) eine Navigationseigenschaft und wurde vollständig vom Client bereitgestellt). Dies liegt daran, dass der Client das gesamte Objekt vom Server empfängt und es mit geringfügigen Änderungen unverändert an den Server zurücksendet.

Andererseits wurde gerade die ObjectB.PropertyY geändert (dies war der Grund für die PUT-Anforderung an erster Stelle).

Da ObjectB.PropertyY ein Verweis auf dasselbe Objekt ObjectA (ein Fremdschlüssel) war, hat EF versucht, dies abzugleichen, und ist mit der obigen Ausnahme fehlgeschlagen.

Die Lösung war einfach:

<code>ObjectB.ObjectA = null;
</code>

bevor die SaveChanges () dies komplett lösten.

Ich hoffe das hilft jemandem.

ar, dass ich der Zuordnung Zuordnungen hinzugefügt und dann die referenziellen Abhängigkeiten eingerichtet habe.

Um das Problem zu beheben, musste ich das Zuordnungsfenster für die Zuordnung öffnen und es gab einen Link zum Löschen der Zuordnungen. Sobald das Fenster "Zuordnungsdetails" abgeschlossen ist, sind diese Zuordnungen nicht mehr zulässig. Es scheint, dass beim Hinzufügen der referenziellen Einschränkung keine Zuordnungen mehr vorhanden sind.

Dachte, es könnte sich lohnen, etwas zu posten, falls jemand nach Lösungen für diese Fehlermeldung in der Zukunft sucht.

. Mein Problem war mit einem Many-Many-Tisch.

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

Ich habe die Zeile hinzugefügt, die ich zugewiesen habePicture = db.Pictures... und dann hat es gut funktioniert (nicht genau sicher warum)

<code>[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());
    }
}
</code>

Ihre Antwort auf die Frage