Gewusst wie: Ausführen von Geschäftslogik beim Speichern von Änderungen (Entity Framework)
Mithilfe von Entity Framework kann benutzerdefinierte Geschäftslogik ausgeführt werden, bevor Änderungen in der Datenbank gespeichert werden. Das SavingChanges-Ereignis wird vor der Ausführung einer SaveChanges-Operation ausgelöst. Behandeln Sie dieses Ereignis, um benutzerdefinierte Geschäftslogik zu implementieren, bevor Änderungen in der Datenbank gespeichert werden. Weitere Informationen zur Implementierung benutzerdefinierter Geschäftslogik finden Sie unter Anpassen von Objekten (Entity Framework). Die Beispiele in diesem Thema zeigen, wie das SavingChanges-Ereignis behandelt wird, um geänderte Objekte im Objektkontext zu überprüfen, bevor diese Änderungen in der Datenbank gespeichert werden.
Das Beispiel in diesem Thema beruht auf dem AdventureWorks Sales-Modell. Um den Code in diesem Beispiel auszuführen, müssen Sie Ihrem Projekt bereits das AdventureWorks Sales-Modell hinzugefügt und das Projekt zur Verwendung von Entity Framework konfiguriert haben. Führen Sie dazu die Verfahren unter Gewusst wie: Manuelles Konfigurieren eines Entity Framework-Projekts und Gewusst wie: Manuelles Definieren eines Entity Data Model (Entity Framework) durch.
Im ersten Beispiel wird dargestellt, wie OnContextCreated zum Registrieren eines Handlers für das SavingChanges-Ereignis in einer Instanz von ObjectContext verwendet wird. Im zweiten Beispiel wird gezeigt, wie dieses Ereignis in einer von ObjectContext abgeleiteten Proxyklasse behandelt wird. Im dritten Beispiel wird Code dargestellt, in dem mithilfe der Proxyklasse aus dem zweiten Beispiel Änderungen an Objekten vorgenommen werden und anschließend SaveChanges aufgerufen wird.
Beispiel
In diesem Beispiel wird die OnContextCreated-Methode als partielle Methode von AdventureWorksEntities definiert. Der Handler für das SavingChanges-Ereignis wird in dieser partiellen Methode definiert. Vom Ereignishandler wird sichergestellt, dass der SalesOrderHeader.Comment-Eigenschaft vom aufrufenden Code kein unpassender Text hinzugefügt wurde, bevor die Änderungen gespeichert werden. Wenn der Algorithmus zum Überprüfen der Zeichenfolge (nicht dargestellt) Probleme findet, wird eine Ausnahme ausgelöst.
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"));
}
}
}
}
}
In diesem Beispiel wird eine Instanz der AdventureWorksProxy-Klasse verwendet, um die Comment-Eigenschaft eines SalesOrderHeader-Objekts zu ändern. Wird SaveChanges für die von der AdventureWorksProxy-Klasse bereitgestellte Instanz von ObjectContext aufgerufen, wird der Validierungscode aus dem vorherigen Beispiel ausgeführt.
' 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());
}
In diesem Beispiel werden in der von ObjectContext abgeleiteten Proxyklasse Änderungen vorgenommen. Anschließend wird SaveChanges aufgerufen. Dieses Beispiel wird verwendet, um die im vorherigen Beispiel dargestellte Ereignisbehandlung aufzurufen.
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"));
}
}
}
}
}
}