Procedura: modificare le relazioni tra gli oggetti (Entity Framework)

In questo argomento viene illustrato come utilizzare l'oggetto EntityReference per modificare una relazione tra due oggetti nel contesto dell'oggetto. Quando viene chiamato il metodo SaveChanges, la modifica della relazione viene resa persistente nel database come modifica alla chiave esterna nella tabella correlata. In questo argomento viene illustrato anche come gestire l'evento AssociationChanged.

L'esempio incluso in questo argomento è basato sul modello Sales di AdventureWorks. Per eseguire il codice incluso in questo esempio, è necessario avere già aggiunto il modello Sales di AdventureWorks al progetto e avere configurato il progetto per l'utilizzo di Entity Framework. A tale scopo, completare le procedure descritte in Procedura: configurare manualmente un progetto di Entity Framework e Procedura: definire manualmente un modello EDM (Entity Framework). È inoltre necessario aggiungere al codice l'istruzione using (Imports in Visual Basic) seguente:

Imports System.ComponentModel
using System.ComponentModel;

Esempio

In questo esempio viene illustrato come utilizzare l'oggetto EntityReference per modificare una relazione tra un oggetto SalesOrderHeader e un oggetto Address correlato che rappresenta l'indirizzo di spedizione per l'ordine.

'Define the order and new address IDs.
Dim orderId As Integer = 43669
Dim newAddressId As Integer = 26

Using context As New AdventureWorksEntities()
    Try
        ' Get the billing address to change to.
        Dim newAddress As Address = context.Address _
            .Where("it.AddressID = @addressId", _
            New ObjectParameter("addressId", newAddressId)) _
        .First()

        ' Get the order being changed.
        Dim order As SalesOrderHeader = context.SalesOrderHeader _
            .Where("it.SalesOrderID = @orderId", _
            New ObjectParameter("orderId", orderId)).First()

        ' Load the current billing address.
        If Not order.Address1Reference.IsLoaded Then
            order.Address1Reference.Load()
        End If

        ' Write the current billing street address.
        Console.WriteLine("Current street: " _
            + order.Address1.AddressLine1)

        ' Change the billing address.
        If Not order.Address1.Equals(newAddress) Then
            order.Address1 = newAddress

            ' Write the changed billing street address.
            Console.WriteLine("Changed street: " _
                + order.Address1.AddressLine1)
        End If

        ' If the address change succeeds, save the changes.
        context.SaveChanges()

        ' Write the current billing street address.
        Console.WriteLine("Current street: " _
            + order.Address1.AddressLine1)
    Catch ex As ApplicationException
        ' Handle the exception raised in the ShippingAddress_Changed 
        ' handler when the status of the order prevents the 
        ' shipping address from being changed. Don't retry because
        ' the relationship is in an inconsistent state and calling 
        ' SaveChanges() will result in an UpdateException.
        Console.WriteLine(ex.ToString())
    Catch ex As InvalidOperationException
        Console.WriteLine(ex.ToString())
    End Try
End Using
// Define the order and new address IDs.
int orderId = 43669;
int newAddressId = 26;

using (AdventureWorksEntities context 
    = new AdventureWorksEntities())
{
    try
    {
        // Get the billing address to change to.
        Address newAddress = context.Address
            .Where("it.AddressID = @addressId",
            new ObjectParameter("addressId", newAddressId))
            .First();

        // Get the order being changed.
        SalesOrderHeader order = context.SalesOrderHeader
            .Where("it.SalesOrderID = @orderId",
            new ObjectParameter("orderId", orderId)).First();

        // Load the current billing address.
        if (!order.Address1Reference.IsLoaded)
        {
            order.Address1Reference.Load();
        }

        // Write the current billing street address.
        Console.WriteLine("Current street: " 
            + order.Address1.AddressLine1);

        // Change the billing address.
        if (!order.Address1.Equals(newAddress))
        {
            order.Address1 = newAddress;

            // Write the changed billing street address.
            Console.WriteLine("Changed street: "
                + order.Address1.AddressLine1);
        }

        // If the address change succeeds, save the changes.
        context.SaveChanges();

        // Write the current billing street address.
        Console.WriteLine("Current street: "
            + order.Address1.AddressLine1);
    }
    catch (ApplicationException ex)
    {
        // Handle the exception raised in the ShippingAddress_Changed 
        // handler when the status of the order prevents the 
        // shipping address from being changed. Don't retry because
        // the relationship is in an inconsistent state and calling 
        // SaveChanges() will result in an UpdateException.
        Console.WriteLine(ex.ToString());
    }
    catch (InvalidOperationException ex)
    {
        Console.WriteLine(ex.ToString());
    }
}

Questo esempio estende l'esempio precedente e illustra come controllare lo stato dell'ordine quando l'indirizzo di spedizione viene modificato gestendo l'evento AssociationChanged su EntityReference per l'oggetto Address che rappresenta l'indirizzo di spedizione. Se lo stato dell'ordine è maggiore di 3, l'ordine non può essere modificato e viene generata un'eccezione. Il delegato è definito nel costruttore per la classe parziale SalesOrderHeader e anche il gestore per questo evento è implementato in questa classe parziale. In questo modo, è possibile assicurarsi che lo stato dell'ordine venga controllato ogni volta che per un ordine viene modificato l'indirizzo di spedizione.

Per convalidare le modifiche all'altra entità finale della relazione SalesOrderHeader-Address, è possibile utilizzare una tecnica simile per registrare l'evento AssociationChanged su un insieme EntityCollection di oggetti SalesOrderHeader correlati a un indirizzo di spedizione.

Partial Public Class SalesOrderHeader
    ' SalesOrderHeader default constructor.
    Public Sub New()
        ' Register the handler for changes to the 
        ' shipping address (Address1) reference.
        AddHandler Me.Address1Reference.AssociationChanged, _
        AddressOf ShippingAddress_Changed
    End Sub

    ' AssociationChanged handler for the relationship 
    ' between the order and the shipping address.
    Private Sub ShippingAddress_Changed(ByVal sender As Object, _
        ByVal e As CollectionChangeEventArgs)
        ' Check for a related reference being removed. 
        If e.Action = CollectionChangeAction.Remove Then
            ' Check the order status and raise an exception if 
            ' the order can no longer be changed.
            If Me.Status > 3 Then
                Throw New ApplicationException( _
                    "The shipping address cannot " _
                + "be changed because the order has either " _
                + "already been shipped or has been cancelled.")
            End If
        End If
    End Sub
End Class
public partial class SalesOrderHeader
{
    // SalesOrderHeader default constructor.
    public SalesOrderHeader()
    {
        // Register the handler for changes to the 
        // shipping address (Address1) reference.
        this.Address1Reference.AssociationChanged
            += new CollectionChangeEventHandler(ShippingAddress_Changed);
    }

    // AssociationChanged handler for the relationship 
    // between the order and the shipping address.
    private void ShippingAddress_Changed(object sender,
        CollectionChangeEventArgs e)
    {
        // Check for a related reference being removed. 
        if (e.Action == CollectionChangeAction.Remove)
        {
            // Check the order status and raise an exception if 
            // the order can no longer be changed.
            if (this.Status > 3)
            {
                throw new ApplicationException(
                    "The shipping address cannot "
                + "be changed because the order has either "
                + "already been shipped or has been cancelled.");
            }
        }
    }
}

Vedere anche

Altre risorse

Utilizzo di oggetti (attività di Entity Framework)