方法: POCO エンティティの変更を検出する
このトピックでは、変更追跡プロキシを使用して POCO エンティティの変更を追跡する方法について説明します。 さらに、DetectChanges メソッドを呼び出して、プロキシを使用せずに変更を検出する方法についても説明します。 ただし、既定では、SaveChanges メソッドは最初に DetectChanges メソッドを呼び出します。 詳細については、「POCO エンティティでの変更の追跡 (Entity Framework)」を参照してください。
このトピックの例では、「方法: POCO エンティティを定義する (Entity Framework)」で定義されている POCO クラスと、「カスタム オブジェクトを操作できるようにモデリング ファイルとマッピング ファイルをカスタマイズする方法 (Entity Framework)」で定義されている AdventureWorks ベースのデータ モデルを使用します。
例
次の例は、Entity Framework で POCO エンティティの変更を追跡するための POCO 自己追跡プロキシを追加します。
' Specify the order to update.
Dim orderId As Integer = 43680
Using context As New POCOAdventureWorksEntities()
Try
' Enable lazy loading.
context.ContextOptions.LazyLoadingEnabled = True
Dim order As Order = context.Orders.Where(Function(o) o.SalesOrderID = orderId).First()
' Create a new item and add it to the order.
' The Entity Framework is going to generate
' proxy object for the newItem object.
Dim newItem As LineItem = context.CreateObject(Of LineItem)()
newItem.SalesOrderDetailID = 0
' Assign the order to the new LineItem.
newItem.SalesOrderID = orderId
newItem.OrderQty = 1
newItem.ProductID = 750
newItem.UnitPriceDiscount = 0
newItem.UnitPrice = 2171.2942D
newItem.ModifiedDate = DateTime.Today
newItem.rowguid = Guid.NewGuid()
newItem.SpecialOfferID = 1
' Add the new item to the order.
' The order will be added to the context because
' we are working with POCO proxies.
order.LineItems.Add(newItem)
' The state of the newItem is Added.
Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(newItem).State.ToString())
' Change the status and ship date of an existing order.
order.ShipDate = DateTime.Today
' The sate of the order item is Modified.
Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(order).State.ToString())
' The newItem is set to Unchanged.
context.SaveChanges()
' Change the newly added item.
newItem.OrderQty = 2
' The changes are tracked as they occur and the state of the object is Modified.
Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(newItem).State.ToString())
' Delete the newly created object.
context.DeleteObject(newItem)
' Save changes in the object context to the database
' after first detecting changes again.
context.SaveChanges()
Catch ex As UpdateException
Console.WriteLine(ex.ToString())
Catch ex As InvalidOperationException
Console.WriteLine(ex.ToString())
End Try
End Using
// Specify the order to update.
int orderId = 43680;
using (POCOAdventureWorksEntities context =
new POCOAdventureWorksEntities())
{
try
{
// Enable lazy loading.
context.ContextOptions.LazyLoadingEnabled = true;
Order order = context.Orders.
Where(o => o.SalesOrderID == orderId).First();
// Create a new item and add it to the order.
// The Entity Framework is going to generate
// proxy object for the newItem object.
LineItem newItem = context.CreateObject<LineItem>();
newItem.SalesOrderDetailID = 0;
// Assign the order to the new LineItem.
newItem.SalesOrderID = orderId;
newItem.OrderQty = 1;
newItem.ProductID = 750;
newItem.UnitPriceDiscount = 0;
newItem.UnitPrice = 2171.2942M;
newItem.ModifiedDate = DateTime.Today;
newItem.rowguid = Guid.NewGuid();
newItem.SpecialOfferID = 1;
// Add the new item to the order.
// The order will be added to the context because
// we are working with POCO proxies.
order.LineItems.Add(newItem);
// The state of the newItem is Added.
Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(newItem).State);
// Change the status and ship date of an existing order.
order.ShipDate = DateTime.Today;
// The sate of the order item is Modified.
Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(order).State);
// The newItem is set to Unchanged.
context.SaveChanges();
// Change the newly added item.
newItem.OrderQty = 2;
// The changes are tracked as they occur and the state of the object is Modified.
Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(newItem).State);
// Delete the newly created object.
context.DeleteObject(newItem);
// Save changes in the object context to the database
// after first detecting changes again.
context.SaveChanges();
}
catch (UpdateException ex)
{
Console.WriteLine(ex.ToString());
}
catch (InvalidOperationException ex)
{
Console.WriteLine(ex.ToString());
}
}
次の例は、ObjectContext によって追跡されない POCO エンティティを追加します。 DetectChanges メソッドは、ObjectStateManager とオブジェクトの現在の状態の同期をとるために呼び出されます。
' Specify the order to update.
Dim orderId As Integer = 43680
Using context As New POCOAdventureWorksEntities()
Try
' Disable proxy object creation.
context.ContextOptions.ProxyCreationEnabled = False
Dim order As Order = context.Orders.Include("LineItems").Where(Function(o) o.SalesOrderID = orderId).First()
' Create a new item and add it to the order.
' The Entity Framework is not going to generate
' a proxy object for the newItem object.
Dim newItem As New LineItem()
newItem.SalesOrderDetailID = 0
' Assign the order to the new LineItem.
newItem.SalesOrderID = orderId
newItem.OrderQty = 1
newItem.ProductID = 750
newItem.UnitPriceDiscount = 0
newItem.UnitPrice = 2171.2942D
newItem.ModifiedDate = DateTime.Today
newItem.rowguid = Guid.NewGuid()
newItem.SpecialOfferID = 1
' Add the new item to the order.
' The order will not be added to the context because
' we are working with pure POCO objects.
order.LineItems.Add(newItem)
Dim entry As ObjectStateEntry = Nothing
' There is no entry for the object because it is not in the context.
context.ObjectStateManager.TryGetObjectStateEntry(newItem, entry)
Console.WriteLine("{0}", If(entry IsNot Nothing, entry.State.ToString(),
"There is no entry for this object"))
' Call DetectChanges to synchronize the objects with the state manager.
context.DetectChanges()
' Try getting the entry after Detectchagnes was called.
context.ObjectStateManager.TryGetObjectStateEntry(newItem, entry)
Console.WriteLine("{0}", If(entry IsNot Nothing, entry.State.ToString(),
"There is no entry for this object"))
' Change the status and ship date of an existing order.
order.ShipDate = DateTime.Today
' Even though we changed the ShipDate of the item in the context
' the status of the order is still Unchanged.
' The changes to the POCO entity without the chane tracking proxy
' are not tracked as they occur.
Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(order).State.ToString())
' Calls DetectChanges(). The newItem is set to Unchanged.
context.SaveChanges()
' Change the newly added item.
newItem.OrderQty = 2
' The state of the newItem is Unchanged.
' If the newItem was a POCO proxy entity the changes would be tracked as they occur
' and the state would be Modified.
Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(newItem).State.ToString())
' Call DetectChanges to synchronize the objects with the state manager.
context.DetectChanges()
' The state of the newItem is now Modified.
Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(newItem).State.ToString())
' Delete the newly created object.
context.DeleteObject(newItem)
' Save changes in the object context to the database
' after first detecting changes again.
context.SaveChanges()
Catch ex As UpdateException
Console.WriteLine(ex.ToString())
Catch ex As InvalidOperationException
Console.WriteLine(ex.ToString())
End Try
End Using
// Specify the order to update.
int orderId = 43680;
using (POCOAdventureWorksEntities context =
new POCOAdventureWorksEntities())
{
try
{
// Disable proxy object creation.
context.ContextOptions.ProxyCreationEnabled = false;
Order order = context.Orders.Include("LineItems").
Where(o => o.SalesOrderID == orderId).First();
// Create a new item and add it to the order.
// The Entity Framework is not going to generate
// a proxy object for the newItem object.
LineItem newItem = new LineItem();
newItem.SalesOrderDetailID = 0;
// Assign the order to the new LineItem.
newItem.SalesOrderID = orderId;
newItem.OrderQty = 1;
newItem.ProductID = 750;
newItem.UnitPriceDiscount = 0;
newItem.UnitPrice = 2171.2942M;
newItem.ModifiedDate = DateTime.Today;
newItem.rowguid = Guid.NewGuid();
newItem.SpecialOfferID = 1;
// Add the new item to the order.
// The order will not be added to the context because
// we are working with pure POCO objects.
order.LineItems.Add(newItem);
ObjectStateEntry entry = null;
// There is no entry for the object because it is not in the context.
context.ObjectStateManager.TryGetObjectStateEntry(newItem, out entry);
Console.WriteLine("{0}", entry!=null ? entry.State.ToString() : "There is no entry for this object");
// Call DetectChanges to synchronize the objects with the state manager.
context.DetectChanges();
// Try getting the entry after Detectchagnes was called.
context.ObjectStateManager.TryGetObjectStateEntry(newItem, out entry);
Console.WriteLine("{0}", entry != null ? entry.State.ToString() : "There is no entry for this object");
// Change the status and ship date of an existing order.
order.ShipDate = DateTime.Today;
// Even though we changed the ShipDate of the item in the context
// the status of the order is still Unchanged.
// The changes to the POCO entity without the chane tracking proxy
// are not tracked as they occur.
Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(order).State);
// Calls DetectChanges(). The newItem is set to Unchanged.
context.SaveChanges();
// Change the newly added item.
newItem.OrderQty = 2;
// The state of the newItem is Unchanged.
// If the newItem was a POCO proxy entity the changes would be tracked as they occur
// and the state would be Modified.
Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(newItem).State);
// Call DetectChanges to synchronize the objects with the state manager.
context.DetectChanges();
// The state of the newItem is now Modified.
Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(newItem).State);
// Delete the newly created object.
context.DeleteObject(newItem);
// Save changes in the object context to the database
// after first detecting changes again.
context.SaveChanges();
}
catch (UpdateException ex)
{
Console.WriteLine(ex.ToString());
}
catch (InvalidOperationException ex)
{
Console.WriteLine(ex.ToString());
}
}
参照
処理手順
方法: POCO エンティティ間のリレーションシップを変更 (Entity Framework)
概念
オブジェクトのカスタマイズ (Entity Framework)
POCO エンティティの使用 (Entity Framework)