2009-05-12 12 views
8

C'è un modo per determinare se un oggetto LINQ non è stato ancora inserito nel database (nuovo) o è stato modificato dall'ultimo aggiornamento (sporco)? Pianifico di legare la mia interfaccia utente a oggetti LINQ (usando WPF) e ho bisogno che si comporti diversamente a seconda che l'oggetto sia già nel database.LINQ to SQL - Tracciamento di oggetti nuovi/sporchi

MyDataContext context = new MyDataContext(); 
MyObject obj; 
if (new Random().NextDouble() > .5) 
    obj = new MyObject(); 
else 
    obj = context.MyObjects.First(); 
// How can I distinguish these two cases? 

L'unica soluzione semplice mi viene in mente è quello di impostare la chiave primaria di nuovi record a un valore negativo (i miei PKs sono un campo di identità e saranno quindi impostati su un numero intero positivo sulla INSERT). Questo funzionerà solo per rilevare nuovi record. Richiede anche PK di identità e richiede il controllo del codice che crea il nuovo oggetto.

C'è un modo migliore per farlo? Sembra che LINQ debba monitorare internamente lo stato di questi oggetti in modo che possa sapere cosa fare su context.SubmitChanges(). C'è un modo per accedere a quello "stato dell'oggetto"?

Chiarimento Apparentemente la mia domanda iniziale era confusa. Non sto cercando un modo per inserire o aggiornare i record. Sto cercando un modo, dato qualsiasi oggetto LINQ, per determinare se quell'oggetto non è stato inserito (nuovo) o è stato modificato dal suo ultimo aggiornamento (sporco).

risposta

14

ChangeSet changes = context.GetChangeSet();

Se changes.Inserts.Contains (yourObject), allora è nuovo e verrà inserito quando viene chiamato SubmitChanges

Se changes.Updates.Contains (yourObject), è già nel database, e sarà aggiornato su SubmitChanges()

1

L'oggetto DataContext traccia internamente le modifiche ai dati in modo da ottimizzare le query SQL generate quando si chiama SubmitChanges().

Se si desidera inserire nuovi oggetti nel database, piuttosto che aggiornare gli oggetti esistenti, si dovrebbe fare qualcosa di simile:

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

Ora, quando si chiama SubmitChanges(), verrà generato sia un INSERT e di un AGGIORNA se necessario. A seconda della velocità con cui hai bisogno di una chiave primaria sul nuovo oggetto, puoi inviarla immediatamente per inviare l'oggetto, svuotare il rilevamento delle modifiche e ottenere la tua nuova chiave primaria.

+1

Questo non è proprio quello che sto cercando. So come inserire/aggiornare usando LINQ. Quello di cui ho bisogno è determinare lo stato di ogni oggetto LINQ dato. –

2

ho creare una classe parziale per ogni oggetto LINQ crea (Data Objects) e hanno ogni oggetto Implementare IDataObject interfaccia

/// <summary> 
/// This interface is used to implement IsNew in all LINQ objects so a Generic Save method 
/// can be used. 
/// </summary> 
public interface IDataObject 
{ 

    #region Properties 


     #region IsNew 
     /// <summary> 
     /// Is this a new object 
     /// </summary> 
     bool IsNew 
     { 
      get; 
     } 
     #endregion 


    #endregion 

} 
#endregion 

in ogni dati dell'oggetto a implementare l'isNew proprietà che restituisca true se il PrimaryKeyè stata impostata:

/// <summary> 
/// Is this a new object 
/// </summary> 
public bool IsNew 
{ 
    get 
    { 
     // initial value 
     bool isNew = (this.CustomerID > 0); 

     // return value 
     return isNew; 
    } 
} 

Poi nel mio DataContext ho lanciato l'Ojbect essere salvato come un IDataObject e se è nuovo io chiamo InsertOnSubmit() prima di chiamare SubmitChanges().

Questo potrebbe non essere il modo più semplice ma consente a tutti gli oggetti di essere salvati genericamente.

Sono necessari alcuni minuti per ogni tabella per implementare l'interfaccia, ma consente di chiamare un metodo generico Save().

0

Sono presenti le interfacce INotifyPropertyChanging e INotifyPropertyChanged con metodi specifici da attivare sull'inserimento che consentono di sapere se l'oggetto si sporca. Se si utilizza SQLMetal, lo fa automaticamente. se scrivi le tue classi di entità, scrivi manualmente il personale idraulico. Ma non sono sicuro che questa soluzione sia adatta dal punto di vista della scalabilità. Non l'ho provato Sembra che potrebbe avere problemi dal momento che spara un evento sulla macchina che fa l'inserimento.