如何:检测 POCO 实体中的更改

本主题介绍如何通过使用更改跟踪代理跟踪 POCO 实体中的更改。 它还介绍如何在没有使用代理的情况下通过调用 DetectChanges 方法检测更改。 请注意,默认情况下 SaveChanges 方法将首先调用 DetectChanges 方法。 有关更多信息,请参见跟踪 POCO 实体中的更改(实体框架)

本主题中的示例使用在如何:定义 POCO 实体(实体框架)中定义的 POCO 类,以及在如何:自定义建模和映射文件以使用自定义对象(实体框架)中定义的基于 AdventureWorks 的数据模型。

示例

此示例添加一个 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 实体之间的关系(实体框架)

概念

自定义对象(实体框架)
使用 POCO 实体(实体框架)