Ajout, modification et suppression d'objets (Entity Framework)

Les objets d'un contexte de l'objet sont des instances de types d'entités qui représentent des données de la source de données. Vous pouvez modifier, créer et supprimer des objets d'un contexte de l'objet ; les services Object Services assurent le suivi des modifications apportées à ces objets. Lorsque la méthode SaveChanges est appelée, les services Object Services génèrent et exécutent des commandes qui exécutent les instructions de mise à jour, d'insertion ou de suppression équivalentes sur la source de données. Pour plus d'informations, voir Enregistrement des modifications et gestion de l'accès concurrentiel (Entity Framework).

Par exemple, supposez que vous exécutez une requête qui retourne un objet SalesOrderHeader et une collection d'objets SalesOrderDetail connexes. Vous pouvez énumérer la collection et effectuer les opérations suivantes :

  • modifier la propriété ShipDate d'une commande ;

  • supprimer un article particulier en appelant la méthode DeleteObject ;

  • ajouter un type d'article à la commande en appelant la méthode Add ;

  • appeler la méthode SaveChanges sur le contexte de l'objet pour enregistrer les modifications apportées aux objets dans la source de données.

L'exemple suivant présente différentes modifications apportées à des objets dans un contexte d'objet :

Dim order As SalesOrderHeader = _
context.SalesOrderHeader.Where( _
        "it.SalesOrderID = @id", New ObjectParameter( _
         "id", orderId)).First()

' Change the status and ship date of an existing order.
order.Status = 1
order.ShipDate = DateAndTime.Today

' Load items for the order, if not already loaded.
If Not order.SalesOrderDetail.IsLoaded Then
    order.SalesOrderDetail.Load()
End If

' Delete the first item in the order.
context.DeleteObject(order.SalesOrderDetail.First())

' Create a new item using the static Create method
' and add it to the order.
order.SalesOrderDetail.Add( _
    SalesOrderDetail.CreateSalesOrderDetail( _
    1, 0, 2, 750, 1, CDec(2171.2942), 0, 0, Guid.NewGuid(), _
    DateAndTime.Today))

' Save changes in the object context to the database.
Dim changes As Integer = context.SaveChanges()
SalesOrderHeader order =
    context.SalesOrderHeader.Where
    ("it.SalesOrderID = @id", new ObjectParameter(
     "id", orderId)).First();

// Change the status and ship date of an existing order.
order.Status = 1;
order.ShipDate = DateTime.Today;

// Load items for the order, if not already loaded.
if (!order.SalesOrderDetail.IsLoaded)
{
    order.SalesOrderDetail.Load();
}

// Delete the first item in the order.
context.DeleteObject(order.SalesOrderDetail.First());

// Create a new item using the static Create method 
// and add it to the order.
order.SalesOrderDetail.Add(
    SalesOrderDetail.CreateSalesOrderDetail(0,
    0, 2, 750, 1, (decimal)2171.2942, 0, 0,
    Guid.NewGuid(), DateTime.Today));

// Save changes in the object context to the database.
int changes = context.SaveChanges();

Ajout d'objets

Lorsque vous voulez insérer des données dans la source de données, vous devez créer une instance d'un type d'entité et ajouter l'objet à un contexte de l'objet. Avant de pouvoir ajouter un nouvel objet, vous devez au préalable définir toutes les propriétés qui ne prennent pas en charge les valeurs null. Pensez à utiliser la méthode CreateObjectName statique du type d'entité pour créer une nouvelle instance d'un type d'entité. Les outils Modèle de données d'entité incluent cette méthode dans chaque classe lorsqu'ils génèrent les types d'entités. Cette méthode Create permet de créer une instance d'un objet et de définir toutes les propriétés de la classe qui ne peuvent pas être null. Elle inclut un paramètre pour chaque propriété dont l'attribut Nullable="false" est appliqué dans le fichier CSDL.

L'exemple suivant utilise la méthode CreateSalesOrderHeader statique pour créer une nouvelle instance de la classe SalesOrderHeader.

' Create a new SalesOrderHeader using the static 
' CreateSalesOrderHeader method.
Dim order As SalesOrderHeader = _
    SalesOrderHeader.CreateSalesOrderHeader( _
    1, Convert.ToByte(1), DateTime.Now, DateTime.Today.AddMonths(2), _
    Convert.ToByte(1), False, String.Empty, customer.ContactID, shipMethod, _
    0, 0, 0, 0, Guid.NewGuid(), DateTime.Now)
// Create a new SalesOrderHeader using the static 
// CreateSalesOrderHeader method.
SalesOrderHeader order = SalesOrderHeader.CreateSalesOrderHeader(0,
    Convert.ToByte(1), DateTime.Now, DateTime.Today.AddMonths(2),
    Convert.ToByte(1), false, string.Empty, customer.ContactID, shipMethod, 
    0, 0, 0, 0, Guid.NewGuid(), DateTime.Now);

Pour plus d'informations, voir Procédure : créer un objet à l'aide d'une méthode create statique (Entity Framework).

Vous pouvez ajouter de nouveaux objets à un contexte de l'objet en appelant la méthode AddObject ou en appelant l'une des méthodes AddToEntitySetName sur l'objet ObjectContext typé. Vous pouvez également ajouter un objet à un contexte de l'objet en l'ajoutant à un objet EntityCollectionexistant. Lorsque vous appelez la méthode Add sur un objet EntityCollection qui n'est pas attaché à un contexte de l'objet, l'objet que vous ajoutez est ajouté au même objet ObjectContext. De la même façon, vous pouvez ajouter un objet en affectant à la nouvelle instance de l'objet la propriété Value d'un objet EntityReference.

Les propriétés de navigation définissent les relations entre les objets. Nous vous recommandons de définir ces propriétés lorsque l'objet est lié à d'autres objets dans le contexte de l'objet. Par exemple, définissez la propriété de relation SalesOrderHeader d'un nouvel objet SalesOrderDetail sur l'instance de la commande à laquelle le type d'article appartient. Lorsque vous créez un nouvel objet lié à un autre objet dans le contexte de l'objet, ajoutez l'objet à l'aide de l'une des méthodes suivantes :

  • Pour une relation un-à-plusieurs ou plusieurs-à-plusieurs, appelez Add surEntityCollection et spécifiez l'objet connexe.

  • Pour une relation un-à-un ou plusieurs-à-un, affectez l'objet connexe à la propriété Value de l'objet EntityReference.

  • Appelez la méthode AddObject pour ajouter le nouvel objet au contexte de l'objet, puis définissez la relation à l'aide de l'une des deux méthodes précédentes.

Vous devez tenir compte des points suivants lors de l'ajout de nouveaux objets :

  • Avant que la méthode SaveChanges soit appelée, les services Object Services génèrent une valeur de clé temporaire pour chaque nouvel objet qui est ajouté à l'aide de la méthode AddObject. Après l'appel à la méthode SaveChanges, la valeur de clé est remplacée par la valeur d'identité attribuée par la source de données lorsqu'une nouvelle ligne est insérée.

  • Si la valeur de clé d'une entité n'est pas générée par la source de données, vous devez attribuer une valeur unique. Si deux objets ont la même valeur de clé spécifiée par l'utilisateur, un objet InvalidOperationException se produit lorsque la méthode SaveChanges est appelée. Dans ce cas, vous devez assigner des valeurs uniques et réessayer l'opération.

  • Entity Framework définit automatiquement des valeurs de clés étrangères dans la source de données lorsque vous définissez une relation entre des objets et que vous appelez SaveChanges. Toutefois, lorsqu'une entité est mappée à des procédures stockées qui effectuent des insertions, des mises à jour et des suppressions, les valeurs de clés étrangères ne sont pas définies automatiquement. Dans ce cas, vous devez affecter correctement aux propriétés qui correspondent à la clé étrangère les valeurs correctes définies pour l'objet connexe. Pour plus d'informations, voir Prise en charge des procédures stockées (Entity Framework).

Modification d'objets

Lorsque vous modifiez une propriété scalaire, complexe ou de navigation d'un objet et que vous appelez SaveChanges, les mises à jour sont envoyées à la source de données. Vous modifiez les relations entre les objets en modifiant les propriétés de navigation, par exemple en modifiant la valeur d'un objet EntityReference ou en supprimant un objet d'un objet EntityCollection. Pour plus d'informations, voir Procédure : modifier les relations entre les objets (Entity Framework).

Les services Object Services assurent le suivi des modifications apportées aux objets qui sont attachés à un objet ObjectContext à l'aide d'une instance de IEntityChangeTracker. Il existe une instance de IEntityChangeTracker pour chaque objet qui est suivi. Les requêtes retournent les objets dans un état Unchanged, à moins que la requête utilise un objet MergeOption ayant la valeur NoTracking. Les outils Modèle de données d'entité génèrent des appels à des méthodes de suivi des modifications dans l'accesseur Set de chaque propriété d'un type d'entité, comme dans l'exemple suivant dans l'accesseur Set de la propriété Status dans la classe SalesOrderHeader.

Set(ByVal value As Byte)
    Me.OnStatusChanging(value)
    Me.ReportPropertyChanging("Status")
    Me._Status = Global.System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value)
    Me.ReportPropertyChanged("Status")
    Me.OnStatusChanged()
End Set
set
{
    this.OnStatusChanging(value);
    this.ReportPropertyChanging("Status");
    this._Status = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value);
    this.ReportPropertyChanged("Status");
    this.OnStatusChanged();
}

La méthode ReportPropertyChanging et la méthode ReportPropertyChanged signalent les modifications de propriété à l'objet IEntityChangeTracker. Si vous utilisez des classes de données personnalisées avec un modèle EDM Modèle de données d'entité, vous devez également signaler les modifications de propriété pour activer le suivi par les services Object Services. Pour plus d'informations, voir Création de rapports de modifications dans les classes de données personnalisées (Entity Framework).

L'état d'un objet passe de Unchanged à Modified chaque fois qu'un accesseur Set de propriété est appelé. Cela se produit même quand la valeur qui est définie est identique à la valeur actuelle. Après l'appel à la méthode AcceptAllChanges, l'état retourné est Unchanged. Par défaut, la méthode AcceptAllChanges est appelée pendant l'opération SaveChanges.

Les outils Modèle de données d'entité génèrent également une paire de méthodes partielles nommées OnPropertyChanging et OnPropertyChanged. Ces méthodes sont appelées dans l'accesseur Set de propriété. Étendez ces méthodes dans des classes partielles pour insérer une logique métier personnalisée pendant des modifications de propriété. Pour plus d'informations, voir Procédure : exécuter la logique métier lors de la modification des propriétés (Entity Framework).

Vous devez tenir compte des points suivants lors de la modification d'objets :

  • Lorsqu'une propriété scalaire ou complexe d'un objet complexe est modifiée, l'état de l'objet entité de niveau supérieur est changé en Modified.

  • Les modifications ne sont pas suivies lorsque les objets sont dans un état Detached. Les objets sont dans cet état quand il est retourné par une requête qui utilise l'option de fusion NoTracking ou après qu'avoir été détaché d'un objet ObjectContext en appelant Detach.

  • Vous pouvez modifier une relation entre deux objets en attribuant la valeur EntityReference à un nouvel objet. Dans ce cas, Entity Framework met automatiquement à jour les valeurs de clés étrangères dans la source de données lorsque vous appelez SaveChanges. Toutefois, lorsqu'une entité est mappée à des procédures stockées qui effectuent des insertions, des mises à jour et des suppressions, les valeurs de clés étrangères ne sont pas automatiquement mises à jour. Dans ce cas, vous devez affecter correctement aux propriétés qui correspondent à la clé étrangère les valeurs correctes définies pour la nouvelle relation. Pour plus d'informations, voir Prise en charge des procédures stockées (Entity Framework).

Suppression d'objets

L'appel de la méthode DeleteObject sur l'objet ObjectContext marque l'objet spécifié comme devant être supprimé. La ligne n'est supprimée de la source de données qu'une fois que la méthode SaveChanges a été appelée.

Vous devez tenir compte des points suivants lors de la suppression d'objets :

  • Lorsqu'un objet est supprimé, toutes les relations à d'autres objets sont également supprimées.

  • Lorsque deux objets se trouvent dans une relation limitée, la suppression de l'objet parent supprime également tous les objets enfants. Ce résultat équivaut à activer la propriété CascadeDelete sur l'association pour la relation. Pour plus d'informations, voir Contraintes référentielles (Entity Framework).

  • Lorsqu'un objet retourné par une requête est lié à un ou plusieurs autres objets, la requête retourne toujours certaines informations relatives à ces objets connexes afin qu'il soit plus facile de supprimer des objets. Dans certains cas, ces informations existantes peuvent lever une exception UpdateException lorsque vous essayez de supprimer un objet. Par exemple, vous recevrez cette exception lorsque l'élément <OnDelete Action="Cascade" /> de l'association qui définit la relation est spécifié dans le parent End de l'élément Association. Lorsque cela se produit, chargez explicitement l'objet connexe avant d'appeler la méthode DeleteObject.

  • Vous pouvez appeler à nouveau la méthode DeleteObject pour un objet qui a déjà été supprimé.

Pour plus d'informations, voir Procédure : ajouter, modifier et supprimer des objets (Entity Framework).

Création d'objets dans un EntitySet spécifique

Il peut arriver qu'un type d'entité appartienne à plusieurs jeux d'entités. Par exemple, imaginons une situation dans laquelle une base de données possède deux tables avec des schémas identiques. Ce peut être le cas si vous souhaitez partitionner les données pour produire un processus de sauvegarde plus efficace. Par exemple, vous pouvez partitionner les données des clients entre les tables Customer et CustomerArchive. La table CustomerArchive a le même schéma que la table Customer mais elle est destinée aux clients qui n'ont pas passé de commandes depuis plus de six mois. Customer pourra par exemple être sauvegardée toutes les nuits, tandis que CustomerArchive ne le sera que de manière hebdomadaire. En ce qui concerne le mappage, Customer et CustomerArchive doivent appartenir à des jeux d'entités différents. Entity Framework prend en charge ce scénario en permettant à un type d'entité d'exister dans un ou plusieurs jeux d'entités. Pour plus d'informations, voir Jeux d'entités (EDM).

Lorsqu'un type d'entité existe dans plusieurs jeux d'entités, Object Services vous permet d'ajouter des instances du type à un jeu d'entités spécifique. Pour cela, vous devez spécifier la valeur de entitySetName lorsque vous appelez la méthode AddObject pour ajouter l'objet au contexte de l'objet. Pour plus d'informations, voir Procédure : ajouter un objet à un jeu d'entités spécifique ((Entity Framework).

Les outils Modèle de données d'entité génèrent également des méthodes AddToEntitySetName sur ObjectContext, avec une méthode pour chaque jeu d'entités défini dans le modèle conceptuel. Ces méthodes appellent AddObject et passent la valeur EntitySetName de la méthode spécifique. Utilisez ces méthodes pour ajouter des objets dans des jeux d'entités spécifiques.

Voir aussi

Tâches

Procédure : définir un modèle avec jeux d'entités multiples par type (Entity Framework)