2010-09-03 56 views
6

Ich lief in ein Problem versucht, ein Fremdschlüsselfeld zu aktualisieren:Wie aktualisiere ich einen Fremdschlüssel effizient in LINQ to SQL/SQLMetal?

record.ForeignId = newId; 

Es Bomben mit „Operation aufgrund des aktuellen Status des Objekts nicht gültig ist“ aufgrund SQLMetal Code, System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException() wirft.

war ich nicht die erste Ausgabe treffen:

LinqToSQL Error : Operation is not valid due to the current state of the object und http://social.msdn.microsoft.com/forums/en-US/linqtosql/thread/f9c4a01a-195a-4f2b-a1cb-e2fa06e28b25/ es diskutieren, unter anderem. diese

ist Ihre Lösung:

record.Foreign = Database.Foreigns.Single(c => c.Id == newId); 

Das ist natürlich eine DB-Lookup für auswärtige verursacht nur ein Objekt zurück zu bekommen, die die Id habe ich schon kennen! Also, wie führe ich dieses Update ohne die sinnlose Abfrage (oder fragt, ob ich viele dieser FKs habe)?

Antwort

3

Sie könnten eine Instanz des übergeordneten Elements (mit der korrekten ID), Attach, es in den Datenkontext als den vorhandenen Datensatzstatus neu erstellen und dann die Parent-Eigenschaft Ihres untergeordneten Objekts zuweisen.

Hier einige Code:

int theId = 5; 
Parent p = new Parent() { Id = theId}; 
dc.Parents.Attach(p); 
child.Parent = p; 
+0

Ich wusste nicht über Attach(), aber ich habe das versucht und einen doppelten Schlüsselfehler erhalten: "Kann keine Entität mit einem Schlüssel hinzufügen, der bereits verwendet wird." Hat es die DB befragt, um das herauszufinden, oder war diese Aufzeichnung vielleicht nur in meinem Datenkontext hängen ...? –

+0

DataContext verfolgt alle Datensätze, die es geladen hat (nach Primärschlüssel). Wenn ein Parent mit ID = 5 geladen wurde, können Sie keine weitere Instanz von Parent mit Id = 5 anhängen. –

+0

Und gibt es eine Möglichkeit zu sehen, ob man im Cache ist und es aussortiert, wenn es das tut? Und sonst gin up ein neues wie in deiner Antwort? Oder vielleicht sag ihm, dass er den ersten fallen lassen sollte? Oder irgendetwas, um dieses Schema funktionieren zu lassen? –

1

Es das Problem nicht lösen, sondern eine Möglichkeit, teilweise um die zusätzliche Last zu erhalten ist, zu überprüfen, um zu sehen, ob der vorhandene Wert als der neue Wert unterscheidet. Wenn es anders ist, wird die Abfrage ausgelöst. Etwas wie -

if(obj.PropertyID != newValue){ 
    obj.Property = PropertyClass.Load(newValue) 
} 
0

Ich hatte das gleiche Problem. Ich habe eine schnelle Lösung gefunden, wahrscheinlich nicht die beste Lösung (da dies die Leistung beeinträchtigen könnte), aber es hat für mich funktioniert.

In meiner Lösung habe ich eine Klasse mit meinem DataContext auf Klassenebene deklariert, so dass ich es überall verwenden kann.

In meiner Lösung alles, was ich tun wollte (ähnlich wie Sie) wurde eine Kontotypen ID zu einem anderen Konto Typ ID (in der Datenbank sind dies FKs) für einen Benutzer geändert.

Da der DataContext bereits geladen war, wurde die Änderung nicht zugelassen. Die Arbeit herum?

Ich habe eine Funktion erstellt, wo ich eine neue Instanz des DataContext erstellen, meine LINQ-Abfrage ausführen, die Änderungen senden und den DataContext anschließend ablegen.