次の方法で共有


変更を保存するときにビジネス ロジックを実行する方法 (Entity Framework)

エンティティ フレームワーク を使用すると、変更内容をデータベースに保存する前にカスタム ビジネス ロジックを実行できます。SavingChanges イベントは、SaveChanges 操作が処理される前に発生します。このイベントを処理して、変更内容をデータベースに保存する前にカスタム ビジネス ロジックを実装します。カスタム ビジネス ロジックの実装方法の詳細については、「オブジェクトのカスタマイズ (Entity Framework)」を参照してください。このトピックの例は、SavingChanges イベントを処理して、オブジェクト コンテキスト内の変更されたオブジェクトがデータベースに保存される前に、これらの変更を検証する方法を示します。

このトピックの例には、Adventure Works Sales Model が使用されています。この例のコードを実行するには、あらかじめプロジェクトに AdventureWorks Sales Model を追加し、エンティティ フレームワーク が使用されるようにプロジェクトを構成しておく必要があります。具体的な方法については、「Entity Framework プロジェクトを手動で構成する方法」および「Entity Data Model を手動で定義する方法 (Entity Framework)」の手順を参照してください。

最初の例は、OnContextCreated を使用して ObjectContext のインスタンスで SavingChanges イベントのハンドラを登録する方法を示しています。2 番目の例は、ObjectContext から派生するプロキシ クラスでこのイベントを処理する方法を示しています。3 番目の例は、2 番目の例のプロキシ クラスを使用してオブジェクトに変更を加え、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"));
                    }
                }
            }
        }
    }
}

参照

その他のリソース

オブジェクトの使用 (Entity Framework タスク)