Gewusst wie: Ändern von Beziehungen zwischen Objekten (Entity Framework)
In diesem Thema wird dargestellt, wie das EntityReference-Objekt verwendet wird, um eine Beziehung zwischen zwei Objekten im Objektkontext zu ändern. Wenn die SaveChanges-Methode aufgerufen wird, wird die Änderung in der Datenbank dauerhaft als eine Änderung am Fremdschlüssel der verknüpften Tabelle gespeichert. Zudem wird die Behandlung des AssociationChanged-Ereignisses erläutert.
Das Beispiel in diesem Thema beruht auf dem AdventureWorks Sales-Modell. Um den Code in diesem Beispiel auszuführen, müssen Sie Ihrem Projekt bereits das AdventureWorks Sales-Modell hinzugefügt und das Projekt zur Verwendung von Entity Framework konfiguriert haben. Führen Sie dazu die Verfahren unter Gewusst wie: Manuelles Konfigurieren eines Entity Framework-Projekts und Gewusst wie: Manuelles Definieren eines Entity Data Model (Entity Framework) durch. Außerdem müssen Sie Ihrem Code die folgende using-Anweisung (Imports in Visual Basic) hinzufügen:
Imports System.ComponentModel
using System.ComponentModel;
Beispiel
In diesem Beispiel wird aufgezeigt, wie das EntityReference-Objekt verwendet wird, um die Beziehung zwischen einem SalesOrderHeader-Objekt und einem verbundenen Address-Objekt zu ändern, das die Lieferadresse der Bestellung darstellt.
'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());
}
}
In diesem Beispiel wird das vorherige Beispiel erweitert und dargestellt, wie der Bestellstatus überprüft wird, wenn die Lieferadresse durch Behandlung des AssociationChanged-Ereignisses der EntityReference für das Address-Objekt, das der Lieferadresse entspricht, geändert wird. Wenn der Bestellstatus größer als 3 ist, kann die Bestellung nicht geändert werden, und es wird eine Ausnahme ausgelöst. Der Delegat wird im Konstruktor für die partielle Klasse SalesOrderHeader definiert. Der Handler für dieses Ereignis wird ebenfalls in dieser partiellen Klasse implementiert. So wird sichergestellt, dass der Bestellstatus immer dann überprüft wird, wenn die Lieferadresse für eine Bestellung geändert wird.
Um die Änderungen am anderen Ende der SalesOrderHeader-Address-Beziehung zu validieren, kann eine ähnliche Technik verwendet werden, um das AssociationChanged-Ereignis in der EntityCollection von SalesOrderHeader-Objekten zu registrieren, die mit einer Lieferadresse verknüpft sind.
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.");
}
}
}
}