HOW TO:在純量屬性變更期間執行商務邏輯 (Entity Framework)
Entity Framework 可讓您在變更產生的屬性之前,先執行自訂商務邏輯,以執行自訂動作。 實體資料模型 工具會產生代表概念模型中之實體的資料類別。 雖然不應該針對每一個產生的屬性直接修改這些產生的類別,不過工具也會產生一對名為 OnPropertyChanging 和 OnPropertyChanged 的部分方法,其中 Property 是屬性名稱。 這些方法會在變更屬性的前後由 Entity Framework 所呼叫,而且您可以在部分資料類別中擴充這些方法來實作自訂程式碼。
注意: |
---|
如果物件層程式碼是使用預設的文字範本以外的文字範本產生的,則可能無法產生部分方法。 |
本主題的範例是根據 Adventure Works Sales Model。 若要執行此範例中的程式碼,您必須已經將 AdventureWorks Sales Model 加入到專案中,並設定您的專案使用 Entity Framework。 若要這樣做,請完成 HOW TO:手動設定 Entity Framework 專案和 HOW TO:手動定義模型和對應檔 (Entity Framework) 中的程序。
若要針對屬性變更實作自訂驗證
在您的專案中,針對每一個要驗證的資料類別定義自訂部分類別。
在此部分類別中,定義下列其中一個或兩個方法,其中 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)