Mike Taulty's Blog
Bits and Bytes from Microsoft UK
Entity Framework - Object Services Level. Deleting and ObjectStateManager.
Mike Taulty's Blog

Mike's Badges

Follow on Twitter
View mike's profile on slideshare
Add to Technorati Favorites
CW Blog Awards

Following the general theme of the last couple of posts (here and here), I thought I'd carry on and experiment with deleting.

   static void Main(string[] args)
    {
      using (NorthwindContext ctx = new NorthwindContext("Name=NorthwindEntities"))
      {
        Shippers s = ctx.Shippers.First();

        ctx.DeleteObject(s);

        DumpObjectStateManager(ctx.ObjectStateManager);

        DumpShippers(ctx.Shippers);
      }
    }
    static void DumpShippers(IEnumerable<Shippers> shippers)
    {
      Console.WriteLine("Dumping");
      foreach (Shippers s in shippers)
      {
        Console.WriteLine("\tShipper id [{0}], name [{1}], tel [{2}]",
          s.ShipperID, s.CompanyName, s.Phone);
      }
    }

Now, a couple of interesting things here. Firstly, when we hit the DumpObjectStateManager we get;

Dumping Object State Manager
        Dumping objects in state [Detached]
        Dumping objects in state [Unchanged]
        Dumping objects in state [Added]
        Dumping objects in state [Deleted]
                Entity from entity set [Shippers], key [<Key=ShipperID,Value=1>]

        Dumping objects in state [Modified]
Dumping
        Shipper id [1], name [Speedy Express], tel [Unlisted]
        Shipper id [2], name [United Package], tel [(503) 555-3199]
        Shipper id [3], name [Federal Shipping], tel [(503) 555-9931]

So, we're in a slightly odd situation here. The ObjectStateManager knows that we've deleted the row but the row still appears in the query that we execute. Naturally, if we commit those changes to the store;

 static void Main(string[] args)
    {
      using (NorthwindContext ctx = new NorthwindContext("Name=NorthwindEntities"))
      {
        Shippers s = ctx.Shippers.Where("it.shipperid = 12").First();

        ctx.DeleteObject(s);

        ctx.SaveChanges(true);

        DumpObjectStateManager(ctx.ObjectStateManager);

        DumpShippers(ctx.Shippers);
      }
    }

Gives the output;

Dumping Object State Manager
        Dumping objects in state [Detached]
        Dumping objects in state [Unchanged]
        Dumping objects in state [Added]
        Dumping objects in state [Deleted]
        Dumping objects in state [Modified]
Dumping
        Shipper id [1], name [Speedy Express], tel [Unlisted]
        Shipper id [2], name [United Package], tel [(503) 555-3199]
        Shipper id [3], name [Federal Shipping], tel [(503) 555-9931]

So, what does this say about what you get back from the ObjectStateManager?

  1. Inserted items will not show up in queries until they've been sent to the store.
  2. Deleted items will show up in queries until they've been removed from the store.
  3. Updated values will show up in results from queries whether they've been transmitted to the store or not.

Now, what happens if you delete an entity that is the parent of a relationship such as a customer and their orders?

      using (NorthwindContext ctx = new NorthwindContext("Name=NorthwindEntities"))
      {
        Customers newCustomer = new Customers()
        {
          CustomerID = "DEMO1",
          CompanyName = "Demo Company"
        };
        Orders newOrder = new Orders();

        newCustomer.Orders.Add(newOrder);

        ctx.AddObject("Customers", newCustomer);

        // Make those changes live in the DB.
        ctx.SaveChanges(true);

        ctx.DeleteObject(newCustomer);
        ctx.SaveChanges(true);
      }

 

This is an interesting one because what happens here is that we update the Order in order to set its CustomerID to null and orphan it away from its owning Customer before we delete it. I can alter that behaviour by changing my CSDL. If I change the CSDL for the relationship to read;

<Association Name="FK_Orders_Customers">
    <End Role="Customers" Type="Northwind.Customers" Multiplicity="0..1">
      <OnDelete Action="Cascade"/>
    </End>
    <End Role="Orders" Type="Northwind.Orders" Multiplicity="*" />
  </Association>

then the same piece of code causes the Order to be deleted rather than orphaned. There seem to be three values for <OnDelete Action=""/> - namely, Restrict, Cascade, None. I can't determine at the time of writing the difference between [Restrict/None] which both seem to orphan the Order.


Posted Mon, Aug 27 2007 4:43 PM by mtaulty

Comments

Guy Burstein's Blog wrote ADO.Net Entity Framework Beta 2 is available
on Mon, Aug 27 2007 10:36 PM
ADO.Net Entity Framework Beta 2 is available The ADO.Net Entity Framework bits for Visual Studio 2008
Mike Taulty's Blog wrote ADO.NET Entity Framework - Bringing Together A Few Previous Posts
on Wed, Aug 29 2007 5:38 PM
This is just a convenience - links to the posts that I've made so far around beta 2 of the ADO.NET Entity...
Entity Framework from Mike Taulty « vincenthome’s Software Development wrote Entity Framework from Mike Taulty &laquo; vincenthome&#8217;s Software Development
on Fri, Sep 7 2007 7:25 AM
Mike Taulty's Blog wrote LINQ to Entities - Deleting
on Wed, Oct 3 2007 1:20 AM
I looked at this before but here I am looking at it again because I think I got it wrong (or only half...
(C) Mike Taulty, 2009. All rights reserved. The information in this weblog is provided "AS IS" with no warranties, and confers no rights. This weblog does not represent the thoughts, intentions, plans or strategies of my employer. It is solely my opinion. Inappropriate comments will be deleted at the authors discretion. All code samples are provided "AS IS" without warranty of any kind, either express or implied, including but not limited to the implied warranties of merchantability and/or fitness for a particular purpose.
Powered by Community Server (Non-Commercial Edition), by Telligent Systems