如何:更改对象间的关系(实体框架)

本主题介绍如何使用 EntityReference 对象在对象上下文中更改两个对象间的关系。调用 SaveChanges 方法时,关系更改将作为相关表中外键的更改永久保留到数据库。本主题还介绍如何处理 AssociationChanged 事件。

本主题中的示例基于 Adventure Works 销售模型。若要运行本示例中的代码,必须已将 AdventureWorks 销售模型添加到您的项目中,并将项目配置为使用 实体框架。为此,请完成如何:手动配置实体框架项目如何:手动定义实体数据模型(实体框架) 中的过程。还必须向代码中添加下列 using 语句(在 Visual Basic 中为 Imports):

Imports System.ComponentModel
using System.ComponentModel;

示例

此示例演示如何使用 EntityReference 对象更改 SalesOrderHeader 对象和表示订单发货地址的相关 Address 对象之间的关系。

'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());
    }
}

此示例扩展前面的示例并显示如何在发货地址更改时检查订单状态,方法是在 EntityReference 上处理表示发货地址的 Address 对象的 AssociationChanged 事件。如果订单状态大于 3,则订单无法更改,将引发异常。构造函数中为 SalesOrderHeader 分部类定义了委托,此事件的处理程序也在该分部类中实现。这将确保在每次订单发货地址更改时都检查订单状态。

要在 SalesOrderHeader-Address 关系的另一端验证更改,可用同样的方法在与发货地址相关的 SalesOrderHeader 对象的 EntityCollection 上注册 AssociationChanged 事件。

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.");
            }
        }
    }
}

另请参见

其他资源

使用对象(实体框架任务)