如何:在保存更改时执行业务逻辑(实体框架)

使用 实体框架 可以在将更改保存到数据库之前执行自定义业务逻辑。SavingChanges 事件在处理 SaveChanges 操作之前引发。处理该事件可以在将更改保存到数据库之前实现自定义业务逻辑。有关如何实现自定义业务逻辑的更多信息,请参见自定义对象(实体框架)。本主题中的示例演示如何处理 SavingChanges 事件,以在将这些更改永久保存到数据库之前验证对象上下文中已更改的对象。

本主题中的示例基于 Adventure Works 销售模型。若要运行本示例中的代码,必须已将 AdventureWorks 销售模型添加到您的项目中,并将项目配置为使用 实体框架。为此,请完成如何:手动配置实体框架项目如何:手动定义实体数据模型(实体框架) 中的过程。

第一个示例演示如何使用 OnContextCreatedObjectContext 的实例中的 SavingChanges 事件注册处理程序。第二个示例演示如何在从 ObjectContext 派生的代理类中处理此事件。第三个示例演示的代码使用第二个示例中的代理类对对象进行更改,然后调用 SaveChanges

示例

在此示例中,OnContextCreated 方法定义为 AdventureWorksEntities 的分部方法。SavingChanges 事件的处理程序在此分部方法中进行定义。该事件处理程序验证在可以持久保存更改之前,调用代码是否未在 SalesOrderHeader.Comment 属性中添加任何不适当的文本。如果字符串校验算法(未显示)发现任何问题,则引发异常。

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"));
                    }
                }
            }
        }
}

在本示例中,AdventureWorksProxy 类的实例用于更改 SalesOrderHeader 对象的 Comment 属性。在 AdventureWorksProxy 类提供的 ObjectContext 实例上调用 SaveChanges 时,将运行上一示例中的验证代码。

' 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());
}

此示例在从 ObjectContext 派生的代理类中对对象进行更改,然后调用 SaveChanges。此示例用于调用在上一个示例中演示的事件处理。

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"));
                    }
                }
            }
        }
    }
}

另请参见

其他资源

使用对象(实体框架任务)