Как выполнить бизнес-логику при изменении скалярных свойств (платформа Entity Framework)
Entity Framework позволяет выполнять собственную пользовательскую бизнес-логику для выполнения пользовательских действий в том случае, если в сформированные свойства были внесены изменения. Средства модели модель EDM (сущностная модель данных) формируют классы данных, представляющие сущности в концептуальной модели. Хотя эти сформированные классы нельзя изменять напрямую, но для каждого из них средства формируют пару разделяемых методов с именами OnСвойствоChanging и OnСвойствоChanged, где Свойство — имя свойства. Эти методы вызываются Entity Framework до и после изменения свойства. Чтобы реализовать пользовательский код, их можно расширить в разделяемых классах данных.
Примечание |
---|
Если код уровня объектов был сформирован при помощи текстового шаблона, отличного от текстового шаблона по умолчанию, то разделяемые методы, возможно, не были сформированы. |
Пример в этом разделе основан на модели Adventure Works Sales. Чтобы запустить код из данного примера, нужно сначала добавить к проекту модель AdventureWorks Sales и настроить его для использования платформы Entity Framework. Для этого выполните инструкции из разделов Как вручную настроить проект Entity Framework и Как определить модель и файлы сопоставления вручную (платформа Entity Framework).
Реализация пользовательской проверки изменений свойств
В проекте определите пользовательский разделяемый класс для каждого проверяемого класса данных.
В этом разделяемом классе определите один или оба следующих метода (Свойство — это имя проверяемого свойства):
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);
}
}
}
}
См. также
Задачи
Как выполнять бизнес-логику при изменении состояния объекта
Как обеспечить выполнение бизнес-логики при изменении ассоциаций
Как выполнять правила бизнес-логики при сохранении изменений (платформа Entity Framework)