如何:更改对象间的关系(实体框架)
本主题介绍如何使用 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.");
}
}
}
}