Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework 4 Entity with EntityState of Unchanged firing update

I am using EF 4, mapping all CUD operations for my entities using sprocs.

I have two tables, ADDRESS and PERSON. A PERSON can have multiple ADDRESS associated with them.

Here is the code I am running:

Person person = (from p in context.People
                             where p.PersonUID == 1
                             select p).FirstOrDefault();

Address address = (from a in context.Addresses
                               where a.AddressUID == 51
                               select a).FirstOrDefault();

address.AddressLn2 = "Test";

context.SaveChanges();

The Address being updated is associated with the Person I am retrieveing - although they are not explicitly linked in any way in the code. When the context.SaveChanges() executes not only does the Update sproc for my Address entity get fired (like you would expect), but so does the Update sproc for the Person entity - even though you can see there was no change made to the Person entity.

When I check the EntityState of both objects before the context.SaveChanges() call I see that my Address entity has an EntityState of "Modified" and my Person enity has an EntityState of "Unchanged".

Why is the Update sproc being called for the Person entity? Is there a setting of some sort that I can set to prevent this from happening?


I created a second project to make sure the issue was not happening because of something in my current project environment.

First, I created a new database that contains an Order and OrderDetail table. They have a foreign key between them so that Order can have more than one OrderDetail associated with it. I also created "after Update" DB triggers on the Order and OrderDetail tables that update a DateTime field when a record is updated.

Second, I created a simple WPF application and created a ADO.NET Entity Model that was generated from my database.

Third, I added code to my class constructor as follows:

public partial class MainWindow : Window
  {
    public MainWindow()
    {
      InitializeComponent();

      MyEntities context = new MyEntities();

      Order order = (from o in context.Orders
              select o).FirstOrDefault();

      OrderDetail orderDetail = (from d in order.OrderDetails
                    select d).FirstOrDefault();

      orderDetail.Qty = 7;

      context.SaveChanges();
    }
  }

I ran the program without doing any function mapping for my Order and OrderDetail objects. The result was exactly what I would expect to see, the OrderDetail record is updated to have a Qty of 7 and the UpdateDateTime field is populated with the date and time the update occurred. No changes to my the Order record which means no update occurred.

I then create stored procedures to handle the update of Order and OrderDetail tables in the DB. They don't do anything special, just accept parameters for every column in the table and then set each field equal to the associated parameter. I then mapped those stored procedures to my Model objects using the Mapping Details (Map Entity to Functions) window.

After doing the mapping, I ran the program. As a result I observed the expected behavior of seeing updates to the OrderDetail table, but in addition the Order table "after Update" trigger had fired and the UdateDateTime field was set to the date and time the update occurred - which I would not expect.

Does anyone know of a way to utilize stored procedures for all Insert, Update and Delete operations and not have the updates cascade up to related entities?

like image 219
Filosopher Avatar asked May 28 '10 18:05

Filosopher


1 Answers

I had this same issue, and it has been solved by the hotfix mentioned on that MS KBD page.

The fix was only published widely in .NET 4.5. However, I expect that EF 6 (which works both on .NET 4 / .NET 4.5) will also ship that fix, as it supersedes the version of System.Data.Entity.dll shipped with .NET 4 with its own.

like image 162
Jean Hominal Avatar answered Oct 19 '22 23:10

Jean Hominal