Procédure : exécuter la logique métier lors de la modification des propriétés (Entity Framework)
Entity Framework vous permet d'exécuter votre logique métier personnalisée afin de réaliser des actions personnalisées lorsque des modifications sont apportées aux propriétés générées. Les outils EDM (Modèle de données d'entité) génèrent des classes de données qui représentent des entités dans un modèle EDM. Bien que ces classes générées ne doivent pas être modifiées directement, pour chaque propriété générée, les outils génèrent également une paire de méthodes partielles nommées OnPropriétéChanging et OnPropriétéChanged, où Propriété est le nom de la propriété. Ces méthodes sont appelées par Object Services avant et après modification d'une propriété. Vous pouvez étendre ces méthodes dans les classes de données partielles de manière à implémenter le code personnalisé. Pour plus d'informations sur la personnalisation des classes générées, consultez Personnalisation des objets (Entity Framework).
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).
Pour implémenter une validation personnalisée des modifications des propriétés
Dans votre projet, définissez une classe partielle personnalisée pour chaque classe de données à valider.
Dans cette classe partielle, définissez l'une des méthodes suivantes, ou les deux, où Propriété est le nom de la propriété à valider :
OnPropriétéChanging - inclure le code à exécuter avant la modification, comme la validation de propriété. Le paramètre value est la nouvelle valeur de la propriété. Implémentez cette méthode pour valider une modification de propriété avant qu'elle n'ait lieu. Pour empêcher la modification, vous devez lever une exception.
OnPropriétéChanged - inclure le code à exécuter après que la modification a eu lieu, comme la journalisation de la modification.
Exemple
Cet exemple vérifie la valeur de SalesOrderHeader.Status pour garantir que la commande peut être modifiée avant qu'une modification soit apportée à SalesOrderDetail.OrderQty et que la modification en attente soit enregistrée dans un fichier. Cette action est réalisée dans la méthode partielle OnOrderQtyChanging. Si la modification ne peut pas être apportée, une exception est levée. Puis, une fois la modification apportée avec succès, la valeur SalesOrderHeader.Status est rétablie à 1 et la modification complète est enregistrée. Ces actions sont réalisées dans la méthode partielle OnOrderQtyChanged.
Partial Public Class SalesOrderDetail
Inherits EntityObject
Private Sub OnOrderQtyChanging(ByVal value As Short)
' Only handle this change for existing SalesOrderHeader
' objects that are attached to an object context. If the item
' is detached then we cannot access or load the related order.
If EntityState <> EntityState.Detached Then
Try
' Ensure that the referenced SalesOrderHeader is loaded.
If Not SalesOrderHeaderReference.IsLoaded Then
SalesOrderHeaderReference.Load()
End If
Dim order As SalesOrderHeader = SalesOrderHeader
' Cancel the change if the order cannot be modified.
If SalesOrderHeader.Status > 3 Then
Throw New ApplicationException("The quantity cannot be changed " _
+ "or the item cannot be added because the order has either " _
+ "already been shipped or has been cancelled.")
End If
' Log the pending order change.
File.AppendAllText(LogFile, "Quantity of item '" _
+ SalesOrderDetailID.ToString() + "' in order '" _
+ order.SalesOrderID.ToString() _
+ "' changing from '" + OrderQty.ToString() _
+ "' to '" + value.ToString() + "'." + Environment.NewLine _
+ "Change made by user: " + Environment.UserName _
+ Environment.NewLine)
Catch ex As InvalidOperationException
Throw New ApplicationException("The quantity could not be changed " _
+ " because the order information could not be retrieved. " _
+ "The following error occurred:" + ex.Message)
End Try
End If
End Sub
Private Sub OnOrderQtyChanged()
' Only handle this change for existing SalesOrderHeader
' objects that are attached to an object context.
If EntityState <> EntityState.Detached Then
Try
' Ensure that the SalesOrderDetail is loaded.
If Not SalesOrderHeaderReference.IsLoaded Then
SalesOrderHeaderReference.Load()
End If
' Reset the status for the order related to this item.
SalesOrderHeader.Status = 1
' Log the completed order change.
File.AppendAllText(LogFile, "Quantity of item '" _
+ SalesOrderDetailID.ToString() + "' in order '" _
+ SalesOrderHeader.SalesOrderID.ToString() _
+ "' successfully changed to '" + OrderQty.ToString() _
+ "'." + Environment.NewLine _
+ "Change made by user: " + Environment.UserName _
+ Environment.NewLine)
Catch ex As InvalidOperationException
Throw New ApplicationException("An error occurred " _
+ "the data could be in an inconsistent state. " _
+ Environment.NewLine + ex.Message)
End Try
End If
End Sub
End Class
public partial class SalesOrderDetail : EntityObject
{
partial void OnOrderQtyChanging(short value)
{
// Only handle this change for existing SalesOrderHeader
// objects that are attached to an object context. If the item
// is detached then we cannot access or load the related order.
if (EntityState != EntityState.Detached)
{
try
{
// Ensure that the referenced SalesOrderHeader is loaded.
if (!this.SalesOrderHeaderReference.IsLoaded)
{
this.SalesOrderHeaderReference.Load();
}
// Cancel the change if the order cannot be modified.
if (this.SalesOrderHeader.Status > 3)
{
throw new ApplicationException("The quantity cannot be changed "
+ "or the item cannot be added because the order has either "
+ "already been shipped or has been cancelled.");
}
// Log the pending order change.
File.AppendAllText(LogFile, "Quantity of item '"
+ this.SalesOrderDetailID.ToString() + "' in order '"
+ this.SalesOrderHeader.SalesOrderID.ToString()
+ "' changing from '" + this.OrderQty.ToString()
+ "' to '" + value.ToString() + "'." + Environment.NewLine
+ "Change made by user: " + Environment.UserName
+ Environment.NewLine);
}
catch (InvalidOperationException ex)
{
throw new ApplicationException("The quantity could not be changed "
+ " because the order information could not be retrieved. "
+ "The following error occurred:" + ex.Message);
}
}
}
partial void OnOrderQtyChanged()
{
// Only handle this change for existing SalesOrderHeader
// objects that are attached to an object context.
if (EntityState != EntityState.Detached)
{
try
{
// Ensure that the SalesOrderDetail is loaded.
if (!SalesOrderHeaderReference.IsLoaded)
{
SalesOrderHeaderReference.Load();
}
// Reset the status for the order related to this item.
this.SalesOrderHeader.Status = 1;
// Log the completed order change.
File.AppendAllText(LogFile, "Quantity of item '"
+ SalesOrderDetailID.ToString() + "' in order '"
+ SalesOrderHeader.SalesOrderID.ToString()
+ "' successfully changed to '" + OrderQty.ToString()
+ "'." + Environment.NewLine
+ "Change made by user: " + Environment.UserName
+ Environment.NewLine);
}
catch (InvalidOperationException ex)
{
throw new ApplicationException("An error occurred; "
+ "the data could be in an inconsistent state. "
+ Environment.NewLine + ex.Message);
}
}
}
}