HOW TO:變更 POCO 實體之間的關聯性 (Entity Framework)
在停用 Proxy 物件的建立或建立 POCO 實體但不包括它的 Proxy 物件時,您必須在 ObjectContext 上呼叫 DetectChanges 方法,才能將變更與 ObjectStateManager 同步化。 除了偵測純量屬性中的變更,這個方法會偵測關聯性中的變更,包括加入、刪除或變更相關物件。 如需詳細資訊,請參閱追蹤 POCO 實體中的變更 (Entity Framework)。 SaveChanges 方法會呼叫 DetectChanges,所以如果您不需要立即同步化關聯性,就不一定要明確呼叫 DetectChanges。
本主題中的範例會使用 HOW TO:定義 POCO 實體 (Entity Framework) 中所定義之 POCO 自訂資料類別,以及 HOW TO:自訂模型與對應檔以搭配自訂物件運作 (Entity Framework) 中所定義之 AdventureWorks 架構資料模型。
範例
此範例會將訂單目前的連絡人變更為不同的連絡人。 在將變更儲存至資料來源之前,SaveChanges 方法會呼叫 DetectChanges 方法。
Using context As New POCOAdventureWorksEntities()
' Disable proxy object creation.
context.ContextOptions.ProxyCreationEnabled = False
Try
' Define the order and new address IDs.
Dim orderId As Integer = 43659
Dim differentContactID As Integer = 5
Dim order As Order = context.Orders.Include("Contact").Where(Function(o) o.SalesOrderID = orderId).First()
' Get contact to change to.
Dim differentContact As Contact = context.Contacts.First(Function(c) c.ContactID = differentContactID)
' The current contact.
Console.WriteLine("Original Contact Name: {0}", order.Contact.FirstName)
' The Entity Framework takes care of setting the other end of the relationship
' when you call DetectChanges or SaveChanges (which calls DetectChanges).
' However, there are scenarios when you are not working with ObjectContext
' and will want to fix both ends of the relationship yourself
' (for example, when working with disconnected objects).
' Change the current ContactID to the new ContactID.
order.ContactID = differentContact.ContactID
' Because the change tracking is not enabled
' The state manager will not be updated untill DetectChanges is called.
' If context.ContextOptions.ProxyCreationEnabled was set to true (which is the default)
' The changes would be synchronized righ away.
Console.WriteLine("The contact was updated, but DetectChanges was not yet called. ")
Console.WriteLine("Contact Name: {0}", order.Contact.FirstName)
context.DetectChanges()
Console.WriteLine("After DetectChanges was called. Contact Name: {0}", order.Contact.FirstName)
' Call save the changes, which calls DetectChanges.
context.SaveChanges()
Catch ex As UpdateException
Console.WriteLine(ex.ToString())
Catch ex As InvalidOperationException
Console.WriteLine(ex.ToString())
End Try
End Using
using (POCOAdventureWorksEntities context =
new POCOAdventureWorksEntities())
{
// Disable proxy object creation.
context.ContextOptions.ProxyCreationEnabled = false;
try
{
// Define the order and new address IDs.
int orderId = 43659;
int differentContactID = 5;
Order order =
context.Orders.Include("Contact")
.Where(o => o.SalesOrderID == orderId).First();
// Get contact to change to.
Contact differentContact = context.Contacts.
First(c => c.ContactID == differentContactID);
// The current contact.
Console.WriteLine("Original Contact Name: {0}", order.Contact.FirstName);
// The Entity Framework takes care of setting the other end of the relationship
// when you call DetectChanges or SaveChanges (which calls DetectChanges).
// However, there are scenarios when you are not working with ObjectContext
// and will want to fix both ends of the relationship yourself
// (for example, when working with disconnected objects).
// Change the current ContactID to the new ContactID.
order.ContactID = differentContact.ContactID;
// Because the change tracking is not enabled
// The state manager will not be updated untill DetectChanges is called.
// If context.ContextOptions.ProxyCreationEnabled was set to true (which is the default)
// The changes would be synchronized righ away.
Console.WriteLine("The contact was updated, but DetectChanges was not yet called. ");
Console.WriteLine("Contact Name: {0}", order.Contact.FirstName);
context.DetectChanges();
Console.WriteLine("After DetectChanges was called. Contact Name: {0}",
order.Contact.FirstName);
// Call save the changes, which calls DetectChanges.
context.SaveChanges();
}
catch (UpdateException ex)
{
Console.WriteLine(ex.ToString());
}
catch (InvalidOperationException ex)
{
Console.WriteLine(ex.ToString());
}
}