Как обнаружить изменения в сущностях 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)