Как обнаружить изменения в сущностях POCO
В этом разделе рассматривается отслеживание изменений в сущностях POCO с помощью прокси-объектов отслеживания изменений. Кроме того, показано, как обнаруживать изменения без прокси-объектов, с помощью вызова метода DetectChanges. Обратите внимание, что по умолчанию метод SaveChanges будет вначале вызывать метод DetectChanges. Дополнительные сведения см. в разделе Отслеживание изменений в сущностях POCO (платформа Entity Framework).
В примерах из этого раздела используются классы POCO, определенные в разделе Как определить сущности POCO (платформа Entity Framework), и модель данных на основе AdventureWorks, определенная в разделе Как настроить файлы моделирования и сопоставления для работы с пользовательскими объектами (платформа Entity Framework).
Пример
В данном примере показано добавление в прокси-объект отслеживания изменений, позволяющего Entity Framework отслеживать изменения в сущности 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());
}
}
В этом примере показано добавление сущности POCO, не отслеживаемой объектом ObjectContext. Метод 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)