2 Stimmen

Wie speichert man ein Linq-Objekt, wenn man seinen Datenkontext nicht kennt?

Ich habe ein Linq-Objekt, und ich möchte Änderungen daran vornehmen und speichern, wie so:

public void DoSomething(MyClass obj) {
  obj.MyProperty = "Changed!";
  MyDataContext dc = new MyDataContext();
  dc.GetTable<MyClass>().Attach(dc, true); // throws exception
  dc.SubmitChanges();
}

Die Ausnahme ist:

System.InvalidOperationException: An entity can only be attached as modified without original state if it declares a version member or does not have an update check policy.

Es sieht so aus, als hätte ich ein paar Möglichkeiten:

  1. ein Versionsmitglied für jede meiner Linq-Klassen und -Tabellen (mehr als 100), die ich auf diese Weise verwenden muss, anlegen.
  2. den Datenkontext finden, in dem das Objekt ursprünglich erstellt wurde, und diesen verwenden, um Änderungen zu übermitteln.
  3. OnLoaded in jeder Klasse implementieren und eine Kopie dieses Objekts speichern, die ich als Basisobjekt an Attach() übergeben kann.
  4. Zum Teufel mit der Gleichzeitigkeitsprüfung; laden Sie die DB-Version kurz vor dem Anhängen und verwenden Sie diese als Basisobjekt (NOT!!!)

Option (2) scheint die eleganteste Methode zu sein, vor allem, wenn ich einen Weg finden kann, einen Verweis auf den Datenkontext zu speichern, wenn das Objekt erstellt wird. Aber - wie?

Haben Sie eine andere Idee?

EDIT

Ich habe versucht, den Rat von Jason Punyon zu befolgen und ein Gleichzeitigkeitsfeld in einer Tabelle als Testfall zu erstellen. Ich habe alle richtigen Eigenschaften (Zeitstempel = true usw.) für das Feld in der dbml-Datei festgelegt und habe jetzt ein Gleichzeitigkeitsfeld... und einen anderen Fehler:

System.NotSupportedException: An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext.  This is not supported.

Was zum Teufel soll ich also anhängen, wenn nicht eine bestehende Entität? Wenn ich einen neuen Datensatz wollte, würde ich eine InsertOnSubmit() ausführen! Wie sollen Sie also Attach() verwenden?

Bearbeiten - FULL DISCLOSURE

OK, ich sehe schon, es ist Zeit für eine umfassende Erklärung, warum die Standardmuster bei mir nicht funktionieren.

Ich habe versucht, clever zu sein und meine Schnittstellen viel sauberer zu gestalten, indem ich den DataContext vor den "Verbraucher"-Entwicklern versteckt habe. Dies habe ich getan, indem ich eine Basisklasse erstellt habe

public class LinqedTable<T> where T : LinqedTable<T> {
  ...
}

... und jede einzelne meiner Tabellen hat die "andere Hälfte" ihrer generierten Version so deklariert:

public partial class MyClass : LinqedTable<MyClass> {
}

Jetzt LinqedTable hat eine Reihe von Utility-Methoden, vor allem Dinge wie:

public static T Get(long ID) {
  // code to load the record with the given ID
  // so you can write things like:
  //   MyClass obj = MyClass.Get(myID);
  // instead of:
  //   MyClass obj = myDataContext.GetTable<MyClass>().Where(o => o.ID == myID).SingleOrDefault();
}
public static Table<T> GetTable() {
  // so you can write queries like:
  //   var q = MyClass.GetTable();
  // instead of:
  //   var q = myDataContext.GetTable<MyClass>();
}

Natürlich bedeutet dies, wie Sie sich vorstellen können, dass LinqedTable muss irgendwie Zugang zu einem DataContext haben. Bis vor kurzem habe ich dies erreicht, indem ich Caching den DataContext in einem statischen Kontext. Ja, "bis vor kurzem", denn "vor kurzem" entdeckte ich, dass man einen DataContext nicht länger als eine Arbeitseinheit behalten sollte, da sonst alle Arten von Kobolden aus dem Gebälk kommen. Lektion gelernt.

Jetzt weiß ich also, dass ich diesen Datenkontext nicht allzu lange behalten kann... deshalb habe ich angefangen, mit der Erstellung eines DataContext on demand zu experimentieren, der nur auf dem aktuellen Rechner zwischengespeichert wird. LinqedTable Instanz. Dies führte dann zu dem Problem, dass der neu erstellte DataContext nichts mit meinem Objekt zu tun haben will, weil er "weiß", dass er dem DataContext, der ihn erstellt hat, untreu ist.

Gibt es eine Möglichkeit, die DataContext-Informationen auf die LinqedTable zum Zeitpunkt der Erstellung oder Laden zu schieben?

Das ist wirklich eine Posse. Ich möchte auf keinen Fall auf all die Komfortfunktionen verzichten, die ich in das System eingebaut habe. LinqedTable Basisklasse, und ich muss in der Lage sein, den DataContext bei Bedarf loszulassen und ihn zu behalten, solange er noch benötigt wird.

Haben Sie eine andere Idee?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X