Как изменить связи между объектами (платформа Entity Framework)
В данном разделе показывается, как можно использовать объект EntityReference для изменения связи между двумя объектами в контексте объекта. При вызове метода SaveChanges изменение в связи сохраняется в базе данных как изменение во внешнем ключе в связанной таблице. В данном разделе также демонстрируется обработка события AssociationChanged.
Пример в этом разделе основан на модели Adventure Works Sales. Чтобы запустить код, используемый в данном примере, нужно сначала добавить к проекту модель AdventureWorks Sales и настроить его для использования платформы Entity Framework. Для этого выполните инструкции из разделов Как вручную настроить проект Entity Framework и Как определить модель EDM вручную (платформа Entity Framework). Необходимо также добавить в код следующую инструкцию using (Imports в Visual Basic):
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());
}
}
Этот пример расширяет предыдущий пример и показывает, как можно проверить состояние заказа, если адрес доставки был изменен путем обработки события AssociationChanged в экземпляре EntityReference для объекта Address, представляющего адрес доставки. Если состояние запроса больше 3, заказ не может быть изменен и вызывается исключение. Делегат, определенный в конструкторе для разделяемого класса SalesOrderHeader, и обработчик для данного события также реализуются в данном разделяемом классе. Это обеспечивает выполнение проверки состояния заказа при любом изменении адреса доставки заказа.
Проверить изменения на другой стороне связи SalesOrderHeader-Address можно путем регистрации события AssociationChanged в экземпляре EntityCollection объектов SalesOrderHeader, связанных с адресом доставки.
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.");
}
}
}
}