8 Stimmen

LINQ to SQL - Verfolgung neuer / schmutziger Objekte

Gibt es eine Möglichkeit festzustellen, ob ein LINQ-Objekt noch nicht in die Datenbank eingefügt wurde (neu) oder seit dem letzten Update geändert wurde (dirty)? Ich plane, meine Benutzeroberfläche an LINQ-Objekte zu binden (unter Verwendung von WPF) und benötige, dass es sich je nachdem, ob das Objekt bereits in der Datenbank ist oder nicht, anders verhält.

MyDataContext context = new MyDataContext();
MyObject obj;
if (new Random().NextDouble() > .5)
    obj = new MyObject();
else
    obj = context.MyObjects.First();
// Wie kann ich diese beiden Fälle unterscheiden?

Die einzige einfache Lösung, die mir einfällt, ist, den primären Schlüssel neuer Datensätze auf einen negativen Wert zu setzen (meine PKs sind ein Identitätsfeld und werden daher bei INSERT auf eine positive Ganzzahl gesetzt). Dies funktioniert nur zur Erkennung neuer Datensätze. Es erfordert auch Identitäts-PKs und die Kontrolle über den Code, der das neue Objekt erstellt.

Gibt es einen besseren Weg, um dies zu tun? Es scheint, dass LINQ intern den Status dieser Objekte verfolgen muss, so dass es weiß, was bei context.SubmitChanges() zu tun ist. Gibt es eine Möglichkeit, auf diesen "Objektstatus" zuzugreifen?

Klärung Offenbar war meine ursprüngliche Frage verwirrend. Ich suche nicht nach einer Möglichkeit, Datensätze einzufügen oder zu aktualisieren. Ich suche eine Möglichkeit, anhand eines beliebigen LINQ-Objekts festzustellen, ob dieses Objekt nicht eingefügt wurde (neu) oder seit dem letzten Update geändert wurde (dirty).

14voto

Eivind T Punkte 1059

ChangeSet changes = context.GetChangeSet();

Wenn changes.Inserts.Contains(yourObject) enthält, ist es neu und wird beim Aufruf von SubmitChanges eingefügt.

Wenn changes.Updates.Contains(yourObject) enthält, ist es bereits in der Datenbank und wird beim Aufruf von SubmitChanges aktualisiert.

2voto

Ich erstelle eine Teilklasse für jedes Objekt, das LINQ erstellt (Datenobjekte) und lasse jedes Objekt das IDataObject-Interface implementieren

/// 
/// Dieses Interface wird verwendet, um IsNew in allen LINQ-Objekten zu implementieren, damit eine generische Speichermethode verwendet werden kann.
/// 
public interface IDataObject
{

    #region Eigenschaften

        #region IsNew
        /// 
        /// Handelt es sich um ein neues Objekt?
        /// 
        bool IsNew
        {
            get;
        } 
        #endregion

    #endregion

} 
#endregion

In jedem Datenobjekt implementiere ich die IsNew-Eigenschaft, um true zurückzugeben, wenn der Primärschlüssel festgelegt wurde:

/// 
/// Handelt es sich um ein neues Objekt?
/// 
public bool IsNew
{
    get
    {
        // Anfangswert
        bool isNew = (this.CustomerID > 0);

        // Rückgabewert
        return isNew;
    }
}

Dann im DataContext cast ich das Objekt, das gespeichert werden soll, als IDataObject und wenn es neu ist, rufe ich InsertOnSubmit() auf, bevor ich SubmitChanges() aufrufe.

Dies ist vielleicht nicht der einfachste Weg, aber er ermöglicht es, alle Objekte generisch zu speichern.

Es dauert ein paar Minuten, um das Interface für jede Tabelle zu implementieren, aber es ermöglicht das Aufrufen einer generischen Save()-Methode.

1voto

womp Punkte 113535

Das DataContext-Objekt verfolgt intern Änderungen an den Daten, um die SQL-Abfragen zu optimieren, die generiert werden, wenn Sie SubmitChanges() aufrufen.

Wenn Sie neue Objekte in die Datenbank einfügen möchten, anstatt vorhandene Objekte zu aktualisieren, sollten Sie etwas Ähnliches tun:

MyDataContext context = new MyDataContext();
MyObject obj;
if (new Random().NextDouble() > .5)
{
    obj = new MyObject();
    context.MyObjects.InsertAllOnSubmit(obj);
}
else
    obj = context.MyObjects.First();

Wenn Sie jetzt SubmitChanges() aufrufen, generiert es sowohl ein INSERT als auch ein UPDATE, wenn nötig. Je nachdem, wie schnell Sie einen Primärschlüssel für Ihr neues Objekt benötigen, könnten Sie es sofort einreichen, um das Objekt einzureichen, die Änderungsnachverfolgung zu leeren und Ihren neuen Primärschlüssel zu erhalten.

1 Stimmen

Das entspricht nicht ganz dem, was ich suche. Ich weiß, wie man mit LINQ einfügt / aktualisiert. Was ich brauche, ist, den Status eines beliebigen LINQ-Objekts zu bestimmen.

0voto

Es gibt INotifyPropertyChanging und INotifyPropertyChanged-Schnittstellen, die spezifische Methoden haben, die bei der Einfügung ausgelöst werden, um Sie darüber zu informieren, ob das Objekt geändert wurde. Wenn Sie SQLMetal verwenden, geschieht dies automatisch. Wenn Sie Ihre eigenen Entitätsklassen schreiben, müssen Sie diese Verwaltungsaufgaben manuell schreiben. Aber ich bin mir nicht sicher, ob diese Lösung aus Skalierbarkeitssicht geeignet ist. Ich habe es nicht getestet. Es scheint, dass es Probleme geben könnte, da ein Ereignis auf dem Computer ausgelöst wird, der die Einfügung durchführt.

0voto

Michael Freidgeim Punkte 23629

Die Frage Wie kann ich einer LINQ-to-SQL-Entität eine "IsDirty"-Eigenschaft hinzufügen? hat eine Antwort von ongle, wie man die IsDirty-Eigenschaft mithilfe des PropertyChanged-Ereignisses implementiert.

Einschränkung: Es zeigt IsDirty als wahr an, wenn eine Eigenschaft geändert wurde, aber dann rückgängig gemacht wurde.

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