Stati di oggetti e rilevamento di modifiche

Agli oggetti LINQ to SQL è sempre associato uno stato. Ad esempio, quando in LINQ to SQL viene creato un nuovo oggetto, lo stato dell'oggetto è Unchanged. Un nuovo oggetto creato dall'utente è sconosciuto all'oggetto DataContext e si trova nello stato Untracked. Dopo la corretta esecuzione di SubmitChanges, tutti gli oggetti riconosciuti da LINQ to SQL sono nello stato Unchanged. La sola eccezione è rappresentata dagli oggetti eliminati dal database che sono nello stato Deleted e di conseguenza inutilizzabili in quell'istanza di DataContext.

Stati degli oggetti

Nella tabella riportata di seguito sono elencati gli stati possibili per gli oggetti LINQ to SQL.

Provincia Descrizione
Untracked Oggetto non rilevato da LINQ to SQL. Di seguito sono illustrati alcuni esempi.

- Un oggetto per cui non è stata eseguita una query tramite l'istanza corrente di DataContext. Ad esempio, un oggetto appena creato.
- Un oggetto creato tramite deserializzazione
- Un oggetto per cui è stata eseguita una query tramite una diversa istanza di DataContext.
Unchanged Un oggetto recuperato usando l'istanza corrente di DataContext e che non risulta modificato da quando è stato creato.
PossiblyModified Un oggetto associato a un'istanza di DataContext. Per altre informazioni, vedere Recupero di dati e operazioni CUD in applicazioni a più livelli (LINQ to SQL).
ToBeInserted Un oggetto non recuperato usando l'istanza corrente di DataContext. In questo caso viene eseguita un'operazione INSERT in un database durante l'esecuzione di SubmitChanges.
ToBeUpdated Un oggetto che risulta modificato da quando è stato recuperato. In questo caso viene eseguita un'operazione UPDATE in un database durante l'esecuzione di SubmitChanges.
ToBeDeleted Un oggetto contrassegnato per l'eliminazione, che causa un'operazione DELETE in un database durante l'esecuzione di SubmitChanges.
Deleted Un oggetto eliminato nel database. Questo stato è finale e non consente transizioni aggiuntive.

Inserimento di oggetti

È possibile richiedere Inserts usando InsertOnSubmit in modo esplicito. In alternativa, in LINQ to SQL è possibile dedurre l'oggetto Inserts mediante la ricerca di oggetti collegati a uno degli oggetti conosciuti che devono essere aggiornati. Ad esempio, se si aggiunge un oggetto Untracked a un oggetto EntitySet<TEntity> o si imposta un oggetto EntityRef<TEntity> su un oggetto Untracked, si rende raggiungibile l'oggetto Untracked mediante gli oggetti rilevati nel grafico. Durante l'elaborazione dell'oggetto SubmitChanges, in LINQ to SQL vengono attraversati gli oggetti rilevati e individuato qualsiasi oggetto persistente raggiungibile di cui non è stata tenuta traccia. Tali oggetti sono candidati per l'inserimento nel database.

Per le classi in una gerarchia di ereditarietà, InsertOnSubmit(o) imposta inoltre il valore del membro definito come discriminatore in modo che corrisponda al tipo dell'oggetto o. Qualora un tipo dovesse corrispondere al valore discriminante predefinito, questa azione causerà la sovrascrittura del valore discriminante con il valore predefinito. Per altre informazioni, vedere Supporto sull'ereditarietà.

Importante

Un oggetto aggiunto a un oggetto Table non si trova nella cache delle identità, che riflette solo gli oggetti recuperati dal database. Dopo una chiamata a InsertOnSubmit, l'entità aggiunta non viene visualizzata nelle query eseguite sul database finché non si completerà SubmitChanges.

Eliminazione di oggetti

Per contrassegnare per l'eliminazione un oggetto o rilevato, chiamare DeleteOnSubmit(o) sull'oggetto Table<TEntity> appropriato. LINQ to SQL considera la rimozione di un oggetto da EntitySet<TEntity> come un’operazione di aggiornamento e il valore della chiave esterna corrispondente è impostato su Null. La destinazione dell'operazione (o) non viene eliminata dalla relativa tabella. Ad esempio, cust.Orders.DeleteOnSubmit(ord) indica un aggiornamento in cui la relazione tra cust e ord viene interrotta mediante l'impostazione della chiave esterna ord.CustomerID su null. Non causa l'eliminazione della riga che corrisponde a ord.

LINQ to SQL esegue l'elaborazione seguente quando un oggetto viene eliminato (DeleteOnSubmit) dalla relativa tabella:

  • Quando si chiama SubmitChanges, per quell'oggetto viene eseguita un'operazione DELETE.

  • La rimozione non viene propagata agli oggetti correlati, indipendentemente dallo stato di caricamento. In particolare, gli oggetti correlati non vengono caricati per aggiornare la proprietà della relazione.

  • Dopo la corretta esecuzione di SubmitChanges, gli oggetti vengono impostati sullo stato Deleted. Di conseguenza non sarà possibile usare l'oggetto o il relativo id in un'istanza di DataContext. La cache interna gestita da un'istanza di DataContext non elimina gli oggetti recuperati o aggiunti come nuovi, anche dopo che sono stati eliminati nel database.

È possibile chiamare DeleteOnSubmit solo su un oggetto registrato da DataContext. Per un oggetto Untracked è necessario chiamare Attach prima di DeleteOnSubmit. Chiamando DeleteOnSubmit su un oggettoUntracked, verrà generata un'eccezione.

Nota

La rimozione di un oggetto da una tabella indica a LINQ to SQL di generare un comando SQL DELETE corrispondente al momento di SubmitChanges. Questa azione non rimuove l'oggetto dalla cache, né propaga l'eliminazione agli oggetti correlati.

Per recuperare l'id di un oggetto eliminato, usare una nuova istanza di DataContext. Per la pulizia degli oggetti correlati è possibile usare la funzionalità del database per la propagazione in cascata di un'eliminazione oppure eliminare manualmente gli oggetti correlati.

Non è necessario, a differenza del database, eliminare gli oggetti correlati in un ordine particolare.

Aggiornamento di oggetti

È possibile rilevare l'esecuzione di Updates osservando le notifiche delle modifiche, che vengono fornite tramite l'evento PropertyChanging nei metodi per l'impostazione delle proprietà. Quando LINQ to SQL riceve una notifica della prima modifica a un oggetto, crea una copia dell'oggetto e lo considera candidato per la generazione di un'istruzione Update.

Per gli oggetti che non implementano l'oggetto INotifyPropertyChanging, in LINQ to SQL viene mantenuta una copia dei valori degli oggetti quando sono stati materializzati per la prima volta. Quando si chiama l'oggetto SubmitChanges, in LINQ to SQL vengono confrontati i valori originali e correnti per stabilire se l'oggetto è stato modificato.

Per gli aggiornamenti delle relazioni, il riferimento dal figlio al padre, ovvero il riferimento che corrisponde alla chiave esterna, viene considerato autorevole. Il riferimento nella direzione inversa, ovvero da padre a figlio, è facoltativo. Le classi di relazione (EntitySet<TEntity> e EntityRef<TEntity>) assicurano che i riferimenti bidirezionali siano coerenti per le relazioni uno-a-molti e uno-a-uno. Se il modello a oggetti non usa EntitySet<TEntity> o EntityRef<TEntity> e se è presente il riferimento inverso, sarà necessario mantenerlo coerente con il riferimento in avanti quando viene aggiornata la relazione.

Se si aggiornano sia il riferimento obbligatorio che la chiave esterna corrispondente, è necessario assicurarsi che corrispondano. Se non sono entrambi sincronizzati quando si chiama InvalidOperationException, verrà generata un'eccezione SubmitChanges. Anche se le modifiche dei valori della chiave esterna sono sufficienti per interessare un aggiornamento della riga sottostante, è necessario modificare il riferimento per mantenere la connettività dell'oggetto grafico e la coerenza bidirezionale delle relazioni.

Vedi anche