Cómo: Ejecutar la lógica empresarial durante los cambios de propiedades escalares (Entity Framework)

Entity Framework permite ejecutar una lógica empresarial propia personalizada para realizar acciones personalizadas cuando se realizan cambios en propiedades generadas. Las herramientas de Entity Data Model generan clases de datos que representan las entidades en un modelo conceptual. Aunque estas clases generadas no se deben modificar directamente, para cada propiedad generada, las herramientas generan también un par de métodos parciales denominados OnPropiedadChanging y OnPropiedadChanged, donde Propiedad es el nombre de la propiedad. Estos métodos son invocados por Entity Framework antes y después de cambiar una propiedad, y se pueden extender en clases de datos parciales para implementar código personalizado.

Cc716747.note(es-es,VS.100).gifNota:
Si el código del nivel de objeto se hubiera generado con una plantilla de texto distinta de una plantilla de texto predeterminada, los métodos parciales podrían no haberse generado .

El ejemplo de este tema se basa en el modelo Adventure Works Sales. Para ejecutar el código de este ejemplo, se debe haber agregado ya el modelo AdventureWorks Sales al proyecto y haber configurado el proyecto para usar Entity Framework. Para ello, complete los procedimientos de Cómo configurar manualmente un proyecto de Entity Framework y Cómo: Definir manualmente los archivos de asignación y modelo (Entity Framework).

Para implementar la validación personalizada en los cambios de propiedades

  1. En el proyecto, defina una clase parcial personalizada para la validación de cada clase de datos.

  2. En esta clase parcial, defina uno o ambos de los métodos siguientes, donde Property es el nombre de la propiedad que se desea validar:

    • On Property Changing: incluya el código que se ha de ejecutar antes de que se produzca el cambio, por ejemplo, la validación de la propiedad. El parámetro value es el valor con el que se cambia la propiedad. Implemente este método para validar un cambio de propiedad antes de que se produzca. Para evitar que se realice el cambio, debe producir una excepción.

    • On Property Changed: incluya el código que se ha de ejecutar después de que se produzca el cambio, por ejemplo, el registro del cambio.

Ejemplo

En este ejemplo se comprueba el valor de SalesOrderHeader.Status para asegurarse de que se puede cambiar el orden antes de realizar un cambio en SalesOrderDetail.OrderQty y el cambio pendiente se registre en un archivo. Esta acción se realiza en el método parcial OnOrderQtyChanging. Si el cambio no se puede realizar, se produce una excepción. A continuación, una vez efectuado correctamente el cambio, el valor de SalesOrderHeader.Status se restablece en 1 y se registra el cambio completado. Estas acciones se realizan en el método parcial 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);
            }
        }
    }
}

Vea también

Tareas

Cómo: Ejecutar la lógica de negocios cuando el estado del objeto cambia
Cómo: Ejecutar la lógica de negocios durante los cambios de asociación
Cómo: Ejecutar la lógica de negocios al guardar los cambios (Entity Framework)

Otros recursos

Entity Data Model Tools