HOW TO:在純量屬性變更期間執行商務邏輯 (Entity Framework)

Entity Framework 可讓您在變更產生的屬性之前,先執行自訂商務邏輯,以執行自訂動作。 實體資料模型 工具會產生代表概念模型中之實體的資料類別。 雖然不應該針對每一個產生的屬性直接修改這些產生的類別,不過工具也會產生一對名為 OnPropertyChangingOnPropertyChanged 的部分方法,其中 Property 是屬性名稱。 這些方法會在變更屬性的前後由 Entity Framework 所呼叫,而且您可以在部分資料類別中擴充這些方法來實作自訂程式碼。

Cc716747.note(zh-tw,VS.100).gif注意:
如果物件層程式碼是使用預設的文字範本以外的文字範本產生的,則可能無法產生部分方法。

本主題的範例是根據 Adventure Works Sales Model。 若要執行此範例中的程式碼,您必須已經將 AdventureWorks Sales Model 加入到專案中,並設定您的專案使用 Entity Framework。 若要這樣做,請完成 HOW TO:手動設定 Entity Framework 專案HOW TO:手動定義模型和對應檔 (Entity Framework) 中的程序。

若要針對屬性變更實作自訂驗證

  1. 在您的專案中,針對每一個要驗證的資料類別定義自訂部分類別。

  2. 在此部分類別中,定義下列其中一個或兩個方法,其中 Property 是要驗證的屬性名稱:

    • On 屬性 Changing - 包含變更發生之前所要執行的程式碼,例如屬性驗證。 value 參數是屬性要變更成的值。 請實作這個方法,在屬性變更發生之前進行驗證。 若要避免變更的進行,您必須擲回例外狀況。

    • On 屬性 Changed - 包含變更發生之後所要執行的程式碼,例如記錄變更。

範例

這個範例會檢查 SalesOrderHeader.Status 的值,以確定在變更 SalesOrderDetail.OrderQty 之前可以變更訂單,而且暫止的變更會記錄到檔案中。 這個動作會在 OnOrderQtyChanging 部分方法中執行。 如果無法進行變更,便會引發例外狀況。 因此,在成功進行變更之後,SalesOrderHeader.Status 值會重設為 1,而且會記錄完成的變更。 這些動作會在 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 Me.SalesOrderHeaderReference.IsLoaded Then
                    Me.SalesOrderHeaderReference.Load()
                End If

                ' Cancel the change if the order cannot be modified. 
                If Me.SalesOrderHeader.Status > 3 Then
                    Throw New InvalidOperationException("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 '" & _
                    Me.SalesOrderDetailID.ToString() & "' in order '" & _
                    Me.SalesOrderHeader.SalesOrderID.ToString() & _
                    "' changing from '" + Me.OrderQty.ToString() & _
                    "' to '" & value.ToString() + "'." & Environment.NewLine & _
                    "Change made by user: " & Environment.UserName & _
                    Environment.NewLine)
            Catch ex As InvalidOperationException
                Throw New InvalidOperationException(("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. 
                Me.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 InvalidOperationException(("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 InvalidOperationException("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 InvalidOperationException("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 InvalidOperationException("An error occurred; "
                + "the data could be in an inconsistent state. "
                + Environment.NewLine + ex.Message);
            }
        }
    }
}

另請參閱

工作

HOW TO:在物件狀態變更時執行商務邏輯
HOW TO:在關聯變更期間執行商務邏輯
HOW TO:在儲存變更時執行商務邏輯 (Entity Framework)

其他資源

Entity Data Model Tools