次の方法で共有


方法: 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)