États des objets et suivi des modifications
Les objets LINQ to SQL participent toujours dans un certain état. Par exemple, quand LINQ to SQL crée un objet, l’état de l’objet est Unchanged
. Quand vous créez un objet, celui-ci est inconnu pour DataContext et son état est Untracked
. Après l’exécution réussie de SubmitChanges, l’état de tous les objets connus dans LINQ to SQL est Unchanged
. La seule exception est représentée par les objets qui ont été supprimés de la base de données, dont l'état est Deleted
, et qui sont inutilisables dans cette instance DataContext.
États des objets
Le tableau suivant liste les états possibles pour les objets LINQ to SQL.
État | Description |
---|---|
Untracked |
Objet non suivi par LINQ to SQL. En voici quelques exemples : - Objet non interrogé dans le DataContext actuel (par exemple, un objet créé récemment). - Objet créé par désérialisation - Objet interrogé par un DataContext différent. |
Unchanged |
Objet récupéré en utilisant le DataContext actuel et dont aucune modification n'est connue depuis sa création. |
PossiblyModified |
Objet attaché à un DataContext. Pour plus d’informations, consultez Extraction de données et opérations CUD dans les applications multicouches (LINQ to SQL). |
ToBeInserted |
Objet qui n'est pas récupéré en utilisant le DataContext actuel. Cela entraîne un INSERT dans la base de données pendant SubmitChanges. |
ToBeUpdated |
Objet dont la modification est connue depuis sa récupération. Cela entraîne un UPDATE dans la base de données pendant SubmitChanges. |
ToBeDeleted |
Objet marqué pour être supprimé, ce qui entraîne une DELETE de la base de données pendant SubmitChanges. |
Deleted |
Objet supprimé dans la base de données. Cet état est définitif et n'autorise pas de transitions supplémentaires. |
Insertion d'objets
Vous pouvez demander explicitement des Inserts
à l'aide de InsertOnSubmit. LINQ to SQL peut également déduire les Inserts
en recherchant des objets connectés à l’un des objets connus qui doit être mis à jour. Par exemple, si vous ajoutez un objet Untracked
à un EntitySet<TEntity> ou si vous affectez un EntityRef<TEntity> à un objet Untracked
, l’objet Untracked
devient accessible à l’aide d’objets suivis dans le graphique. Lors du traitement de SubmitChanges, LINQ to SQL parcourt les objets suivis et identifie tous les objets persistants accessibles qui ne sont pas suivis. Ces objets peuvent être insérés dans la base de données.
Pour les classes d’une hiérarchie d’héritage, InsertOnSubmit(o
) définit également la valeur du membre désigné comme discriminateur pour correspondre au type de l’objet o
. La valeur du discriminateur est par conséquent substituée par la valeur par défaut si un type correspond à la valeur du discriminateur par défaut. Pour plus d’informations, consultez Prise en charge de l’héritage.
Important
Un objet ajouté à un Table
n'est pas dans le cache d'identité. Le cache d'identité reflète uniquement ce qui est récupéré de la base de données. Après un appel à InsertOnSubmit, l'entité ajoutée n'apparaît pas dans les requêtes sur la base de données tant que SubmitChanges ne s'est pas terminé avec succès.
Suppression d'objets
Vous pouvez marquer un objet suivi o
pour le supprimer en appelant DeleteOnSubmit (o) sur le type Table<TEntity> approprié. LINQ to SQL considère la suppression d’un objet d’un EntitySet<TEntity> comme une opération de mise à jour et la valeur de clé étrangère correspondante est Null. La cible de l'opération (o
) n'est pas supprimée de sa table. Par exemple, cust.Orders.DeleteOnSubmit(ord)
indique une mise à jour où la relation entre cust
et ord
est rompue en affectant à la clé étrangère ord.CustomerID
la valeur null. Cela n'entraîne pas la suppression de la ligne qui correspond à ord
.
LINQ to SQL effectue le traitement suivant quand un objet est supprimé (DeleteOnSubmit) de sa table :
Lorsque SubmitChanges est appelé, une opération de
DELETE
est effectuée pour cet objet.La suppression n'est pas propagée aux objets connexes, qu'ils soient chargés ou non. Plus précisément, les objets connexes ne sont pas chargés pour mettre à jour la propriété de relation.
Après l'exécution réussie de SubmitChanges, l'état des objets est
Deleted
. Par conséquent, vous ne pouvez pas utiliser l'objet ou sonid
dans ce DataContext. Le cache interne maintenu par une instance DataContext n'élimine pas les objets qui sont récupérés ou ajoutés comme nouveaux, même après que les objets ont été supprimés dans la base de données.
Vous pouvez appeler DeleteOnSubmit uniquement sur un objet suivi par le DataContext. Pour un objet Untracked
, vous devez appeler Attach avant d'appeler DeleteOnSubmit. L'appel à DeleteOnSubmit sur un objet Untracked
lève une exception.
Notes
La suppression d’un objet d’une table indique à LINQ to SQL de générer une commande SQL DELETE
correspondante au moment de SubmitChanges. Cette action ne supprime pas l'objet du cache ou ne propage pas la suppression aux objets connexes.
Pour récupérer l'id
d'un objet supprimé, utilisez une nouvelle instance DataContext. Pour nettoyer des objets connexes, vous pouvez utiliser la fonctionnalité de suppression en cascade de la base de données ou supprimer manuellement les objets connexes.
Les objets connexes ne doivent pas être supprimés dans un ordre particulier (contrairement aux bases de données).
Mise à jour d'objets
Vous pouvez détecter les Updates
en observant les notifications de modifications. Les notifications sont fournies par l'événement PropertyChanging dans les accesseurs Set de propriété. Quand LINQ to SQL est informé de la première modification d’un objet, il crée une copie de l’objet et considère l’objet comme candidat pour générer une instruction Update
.
Pour les objets qui n’implémentent pas INotifyPropertyChanging, LINQ to SQL conserve une copie des valeurs des objets lors de leur matérialisation. Quand vous appelez SubmitChanges, LINQ to SQL compare les valeurs actuelles et d’origine pour décider si l’objet a été changé.
Pour les mises à jour de relations, la référence de l'enfant au parent (autrement dit, la référence qui correspond à la clé étrangère) est considérée comme l'autorité. La référence dans le sens inverse (autrement dit, du parent à l'enfant) est facultative. Les classes de relation (EntitySet<TEntity> et EntityRef<TEntity>) garantissent la cohérence des références bidirectionnelles pour les relations de type un-à-plusieurs et un-à-un. Si le modèle objet n'utilise pas EntitySet<TEntity> ou EntityRef<TEntity> et si la référence inverse est présente, vous devez respecter la cohérence avec la référence vers l'avant lorsque la relation est mise à jour.
Si vous mettez à jour à la fois la référence requise et la clé étrangère correspondante, vous devez vous assurer de leur correspondance. Une exception InvalidOperationException est levée si elles ne sont pas toutes les deux synchronisés au moment où vous appelez SubmitChanges. Bien que les modifications de valeur de clé étrangère soient suffisantes pour affecter une mise à jour de ligne sous-jacente, vous devez modifier la référence pour maintenir la connectivité du graphique d'objet et la cohérence bidirectionnelle des relations.