find a location for property in a new city

Monday, 14 June 2010

Entity Framework OptimisticConcurrencyException

I got an OptimisticConcurrencyException error with description of "Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries." when trying to insert into a table using the Entity Framework 4.

I found that the table I was working on had an INSTEAD OF INSERT on it. This was doing a few things and then returning (0 row(s) affected). Entity Framework wasn't happy with this since it looked as though nothing was being inserted and so threw the confusing OptimisticConcurrencyException error.

Workaround

I've been trying to get this to work for a fancy workaround so a drop will be the order of the day:

DROP TRIGGER [dbo].[trg_PITA]

Job done. The main problem was finding this trigger in the first place since it is not something you normally look at and almost impossible to debug.

Better workaround

Almost 3 years later! Rachel Peirson has come up with a workaround to this problem that also allows you to keep your trigger in place. Please see her comments below for details.

Follow britishdev on Twitter

11 comments:

  1. Deleting of trigger is not a solution.

    ReplyDelete
  2. Replies
    1. Hence the title "Workaround"

      Just letting you know the cause to save you several hours of head scratching. If you have a solution please share. Although, we are on EF 5.0 now so it may well have been fixed since I originally discovered this bug

      Delete
  3. Still a problem at present. Bugger, I needed that INSTEAD OF INSERT, UPDATE, DELETE Trigger as well.

    ReplyDelete
    Replies
    1. In case anybody else is still having trouble with this, I found that the error was caused by Entity Framework getting confused by the ROWCOUNT being reported by Sql Server. This is a problem even though the ROWCOUNT is reported correctly when you run UPDATE commands, etc, within Enterprise Manager.

      The solution is to add the following SELECT statement at the end of your Trigger:

      SELECT * FROM deleted UNION ALL
      SELECT * FROM inserted;

      This causes a SELECT with the appropriate number of rows to keep Entity Framework happy. Looks a bit messy when you use Enterprise Manager, though, and get resulting SELECTs you don't need. Grrrr!

      Delete
    2. Rachel! Awesome find! Thanks for posting that. Seems to be working. It's the best workaround I've seen so far.

      Thanks!

      Delete
    3. Excellent! Thanks so much for finding a proper solution to work around the cause. I'll mention your solution in an update to my post

      Delete
    4. A couple issues you will run into with this solution is that returning results from triggers is deprecated in SQL Server (http://msdn.microsoft.com/en-us/library/ms143729.aspx) and the UNION ALL means that an UPDATE statement would return 2 rows for every update since an UPDATE populates both the inserted and deleted virtual table.

      Delete
  4. Great suggestion Rachel.... :) it worked for me finally after trying so many things.

    Akhil.

    ReplyDelete
  5. This saved my bacon...hours I spend trying to figure out what was going wrong. 4 years later! Thanks Rachel!

    ReplyDelete
  6. The blog or and best that is extremely useful to keep I can share the ideas
    of the future as this is really what I was looking for, I am very comfortable and pleased to come here. Thank you very much.
    tanki online | 2048 game|

    ReplyDelete