Procédure : exécuter la logique métier lors de l'enregistrement de modifications (Entity Framework)
Entity Framework vous permet d'exécuter la logique métier personnalisée avant que les modifications ne soient enregistrées dans la base de données. L'événement SavingChanges est déclenché avant exécution d'une opération SaveChanges. Gérez cet événement pour implémenter la logique métier personnalisée avant que les modifications ne soient enregistrées dans la base de données. Pour plus d'informations sur l'implémentation de la logique métier personnalisée, voir Personnalisation des objets (Entity Framework). Les exemples de cette rubrique montrent comment gérer l'événement SavingChanges pour valider les objets modifiés dans un contexte d'objet avant que ces modifications ne soient rendues persistantes dans la base de données.
L'exemple de cette rubrique est basé sur le modèle de vente Adventure Works Sales Model. Pour exécuter le code de cet exemple, vous devez déjà avoir ajouté le modèle de vente AdventureWorks Sales Model à votre projet et configuré ce dernier pour qu'il utilise Entity Framework. Pour ce faire, exécutez les procédures décrites dans Procédure : configurer manuellement un projet Entity Framework et Procédure : définir manuellement un modèle EDM (Entity Data Model) (Entity Framework).
Le premier exemple montre comment utiliser OnContextCreated pour inscrire un gestionnaire pour l'événement SavingChanges dans une instance de ObjectContext. Le deuxième exemple montre comment gérer cet événement dans une classe proxy dérivée de ObjectContext. Le troisième exemple présente du code qui modifie des objets en utilisant la classe proxy du deuxième exemple et qui appelle ensuite SaveChanges.
Exemple
Dans cet exemple, la méthode OnContextCreated est définie comme étant une méthode partielle de AdventureWorksEntities. Le gestionnaire de l'événement SavingChanges est défini dans cette méthode partielle. Le gestionnaire d'événements vérifie que le code appelant n'a pas ajouté de texte inapproprié dans la propriété SalesOrderHeader.Comment avant de rendre les modifications persistantes. Si l'algorithme de vérification de chaîne (non illustré) trouve des problèmes, une exception est levée.
Partial Public Class AdventureWorksEntities
Private Sub OnContextCreated()
' Register the handler for the SavingChanges event.
AddHandler Me.SavingChanges, _
AddressOf context_SavingChanges
End Sub
' SavingChanges event handler.
Private Sub context_SavingChanges(ByVal sender As Object, ByVal e As EventArgs)
Dim context As ObjectContext = CType(sender, ObjectContext)
' Validate the state of each entity in the context
' before SaveChanges can succeed.
For Each entry As ObjectStateEntry In _
context.ObjectStateManager.GetObjectStateEntries( _
EntityState.Added Or EntityState.Modified)
' Find an object state entry for a SalesOrderHeader object.
If (Not entry.IsRelationship) And _
(TypeOf entry.Entity Is SalesOrderHeader) Then
Dim orderToCheck As SalesOrderHeader = CType(entry.Entity, SalesOrderHeader)
' Call a helper method that performs string checking
' on the Comment property.
Dim textNotAllowed As String = ValidatorObjectContext.CheckStringForLanguage( _
orderToCheck.Comment)
' If the validation method returns a problem string, raise an error.
If textNotAllowed <> String.Empty Then
Throw New ApplicationException(String.Format("Changes cannot be " _
+ "saved because the {0} '{1}' object contains a " _
+ "string that is not allowed in the property '{2}'.", _
entry.State, "SalesOrderHeader", "Comment"))
End If
End If
Next
End Sub
End Class
public partial class AdventureWorksEntities
{
partial void OnContextCreated()
{
// Register the handler for the SavingChanges event.
this.SavingChanges
+= new EventHandler(context_SavingChanges);
}
// SavingChanges event handler.
private static void context_SavingChanges(object sender, EventArgs e)
{
// Validate the state of each entity in the context
// before SaveChanges can succeed.
foreach (ObjectStateEntry entry in
((ObjectContext)sender).ObjectStateManager.GetObjectStateEntries(
EntityState.Added | EntityState.Modified))
{
// Find an object state entry for a SalesOrderHeader object.
if (!entry.IsRelationship && (entry.Entity.GetType() == typeof(SalesOrderHeader)))
{
SalesOrderHeader orderToCheck = entry.Entity as SalesOrderHeader;
// Call a helper method that performs string checking
// on the Comment property.
string textNotAllowed = Validator.CheckStringForLanguage(
orderToCheck.Comment);
// If the validation method returns a problem string, raise an error.
if (textNotAllowed != string.Empty)
{
throw new ApplicationException(String.Format("Changes cannot be "
+ "saved because the {0} '{1}' object contains a "
+ "string that is not allowed in the property '{2}'.",
entry.State, "SalesOrderHeader","Comment"));
}
}
}
}
}
Dans cet exemple, une instance de la classe AdventureWorksProxy est utilisée pour modifier la propriété Comment d'un objet SalesOrderHeader. Lorsque la méthode SaveChanges est appelée sur l'instance de l'objet ObjectContext fournie par la classe AdventureWorksProxy, le code de validation de l'exemple précédent est exécuté.
' Create an instance of the proxy class that returns an object context.
Dim proxy As AdventureWorksProxy = New AdventureWorksProxy()
' Get the first order from the context.
Dim order As SalesOrderHeader = proxy.Context.SalesOrderHeader.First()
' Add some text that we want to catch before saving changes.
order.Comment += "Some inappropriate comment."
Try
' Save changes using the proxy class.
proxy.Context.SaveChanges()
Catch ex As ApplicationException
' Handle the exception returned by the proxy class
' validation if a problem string is found.
Console.WriteLine(ex.ToString())
End Try
// Create an instance of the proxy class that returns an object context.
AdventureWorksProxy proxy = new AdventureWorksProxy();
// Get the first order from the context.
SalesOrderHeader order = proxy.Context.SalesOrderHeader.First();
// Add some text that we want to catch before saving changes.
order.Comment += "Some inappropriate comment.";
try
{
// Save changes using the proxy class.
proxy.Context.SaveChanges();
}
catch (ApplicationException ex)
{
// Handle the exception returned by the proxy class
// validation if a problem string is found.
Console.WriteLine(ex.ToString());
}
Cet exemple apporte des modifications à des objets de la classe proxy qui est dérivée de ObjectContext et appelle SaveChanges. Cet exemple vise à appeler la gestion d'événements illustrée dans l'exemple précédent.
Public Class AdventureWorksProxy
' Define the object context to be provided.
Private contextProxy As New AdventureWorksEntities()
Public Sub New()
' When the object is initialized, register the
' handler for the SavingChanges event.
AddHandler contextProxy.SavingChanges, _
AddressOf context_SavingChanges
End Sub
' Method that provides an object context.
Public ReadOnly Property Context() As AdventureWorksEntities
Get
Return Me.contextProxy
End Get
End Property
' SavingChanges event handler.
Private Sub context_SavingChanges(ByVal sender As Object, ByVal e As EventArgs)
' Ensure that we are passed an ObjectContext
Dim context As ObjectContext = CType(sender, ObjectContext)
If (Not sender Is Nothing) And (TypeOf sender Is ObjectContext) Then
' Validate the state of each entity in the context
' before SaveChanges can succeed.
For Each entry As ObjectStateEntry In _
context.ObjectStateManager.GetObjectStateEntries( _
EntityState.Added Or EntityState.Modified)
' Find an object state entry for a SalesOrderHeader object.
If (Not entry.IsRelationship) And _
(TypeOf entry.Entity Is SalesOrderHeader) Then
Dim orderToCheck As SalesOrderHeader = CType(entry.Entity, SalesOrderHeader)
' Call a helper method that performs string checking
' on the Comment property.
Dim textNotAllowed As String = Validator.CheckStringForLanguage( _
orderToCheck.Comment)
' If the validation method returns a problem string, raise an error.
If textNotAllowed <> String.Empty Then
Throw New ApplicationException(String.Format("Changes cannot be " _
+ "saved because the {0} '{1}' object contains a " _
+ "string that is not allowed in the property '{2}'.", _
entry.State, "SalesOrderHeader", "Comment"))
End If
End If
Next
End If
End Sub
End Class
public class AdventureWorksProxy
{
// Define the object context to be provided.
private AdventureWorksEntities contextProxy =
new AdventureWorksEntities();
public AdventureWorksProxy()
{
// When the object is initialized, register the
// handler for the SavingChanges event.
contextProxy.SavingChanges
+= new EventHandler(context_SavingChanges);
}
// Method that provides an object context.
public AdventureWorksEntities Context
{
get
{
return contextProxy;
}
}
// SavingChanges event handler.
private void context_SavingChanges(object sender, EventArgs e)
{
// Ensure that we are passed an ObjectContext
ObjectContext context = sender as ObjectContext;
if (context != null)
{
// Validate the state of each entity in the context
// before SaveChanges can succeed.
foreach (ObjectStateEntry entry in
context.ObjectStateManager.GetObjectStateEntries(
EntityState.Added | EntityState.Modified))
{
// Find an object state entry for a SalesOrderHeader object.
if (!entry.IsRelationship && (entry.Entity.GetType() == typeof(SalesOrderHeader)))
{
SalesOrderHeader orderToCheck = entry.Entity as SalesOrderHeader;
// Call a helper method that performs string checking
// on the Comment property.
string textNotAllowed = Validator.CheckStringForLanguage(
orderToCheck.Comment);
// If the validation method returns a problem string, raise an error.
if (textNotAllowed != string.Empty)
{
throw new ApplicationException(String.Format("Changes cannot be "
+ "saved because the {0} '{1}' object contains a "
+ "string that is not allowed in the property '{2}'.",
entry.State, "SalesOrderHeader","Comment"));
}
}
}
}
}
}