Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq row not found or changed

Error Message: Row not found or changed.
Stack Trace:
at System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode) 
at System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode) 

This occurs seemingly randomly. I get emailed these errors, and the URL reported always seems to work for me and should be functioning for everyone else as well.

I can fix this error by:

  • Going to my dbml layout
  • Selecting every field in the table causing conflicts
  • Right click and set the property Update Check to Never

This seems to prevent these types of errors being thrown.

However, this is laborious to remember to keep doing whenever I make a chance to the dmbl, add new tables, etc. Is there a better way to solve this problem? I'm getting maybe 50-100 of these a day which is bad for my visitors.

like image 860
Tom Gullen Avatar asked Jan 13 '12 13:01

Tom Gullen


4 Answers

I had same issue, and solved it by comparing dbml to db structure. One property wasn't set to nullable, and that was causing the issue.

So check your dbml, and nullable properties.

like image 104
Tomasz Maj Avatar answered Nov 11 '22 20:11

Tomasz Maj


Every time I've seen this error, it means that something changed in the database between the time that I loaded the record/object/whatever and when I was trying to save it. Without fail, it was because my unit of work was too big.

I don't know the exact nature of your application, but I'm assuming you are creating a data context, loading a record or list of records, performing some operations on it, chewing up some time and processor cycles, and then at the end trying to save the modified data back to the database. Maybe even loading an instance of a record/object and storing it in a class variable for a while, and then at the end of a page load or thread or whatever trying to save back anything that changed. The problem is that because LINQ stored a copy of that, that is the copy it wants to update. If the underlying data changes in the meantime, it gets mad.

Ask yourself this, what if you put a locking transaction on your data for the whole lifetime of your objects. Say anything you loaded any may modify, nobody else would be allowed to touch it during that time. Basically that is the assumption here. Granted, LINQ is a little more optimistic about it, no sense in locking the row or table if you may never be updating the data, but you think through those problems. Ask yourself what would break or slow down significantly if you were to put strict transactional locks on your objects, and that will probably point you to the offending code.

My solution to this is to keep my unit of work as small as possible. Don't load the object and use that as your working copy and store it back to the database, all in one context. Instead, load the object and pull out the info you need in one step, then figure out the changes you need to apply, and then load/update/save the object. Sure it causes more round trips to the database, but gives you a better assurance that you are working with the latest copy of data. It will still be "last in, wins", meaning that if someone made an update while you were working with the data it may be lost, but that is always a risk unless you lock the record with a transaction. However, it does buy you the flexiblity that if someone else is modifying unrelated fields in the same row, you both can operate on that data together.

like image 23
Mike Mooney Avatar answered Nov 11 '22 19:11

Mike Mooney


GetTable().Attach(newEntity, originalEntity);

If you're not using a version field to update, The above method parameterize new details and old details entities, if the original entity is changed at this point you'll still get the same error, this is up to you to ensure. This works like a charm, i've tried it.

like image 2
Serame Avatar answered Nov 11 '22 21:11

Serame


This can also happen if a database trigger changes any column in a row you are updating - even if you are not updating that particular column.

You will have to double check that any of the tables affected in your unit of work don't have triggers on them. If you are using update triggers, then you will probably want to make sure the updated columns are NeverCheck.

like image 2
Jacob Avatar answered Nov 11 '22 21:11

Jacob