Last week, I was asked to help on an exception on an ASP.NET page, which was occurring intermittently. The exception was
Message: Sys.WebForms.PageRequestManagerServerErrorException: Row not found or changed.
Initially, I started with Page Requests / Call Stack etc. but nothing seemed obvious. I started looking for other references at Google/ StackOverflow etc.. and finally found it as a LinqToSQL concurrency issue.
Concurrency issues can be tricky and LinqToSQL handles data updates with optimistic concurrency.
What is Optimistic Concurrency:
The technique that first investigates whether other transactions have changed values in a row before permitting changes to be submitted.
Contrast with pessimistic concurrency control, which locks the record to avoid concurrency conflicts.
Optimistic control is so termed because it considers the chances of one transaction interfering with another to be unlikely.
In the LINQ to SQL object model, an optimistic concurrency conflict occurs when both of the following conditions are true:
- The client tries to submit changes to the database.
- One or more update-check values have been updated in the database since the client last read them.
Resolution of this conflict includes
- Discovering which members of the object are in conflict,
- Deciding what you want to do about it.
Conflict Resolution Options:
You can detect and resolve conflicts at any level of detail.
At one extreme, you can resolve all conflicts in one of three ways (see RefreshMode) without additional consideration. At the other extreme, you can designate a specific action for each type of conflict on every member in conflict.
- Specify or revise UpdateCheck options in your object model.
For more information, see How to: Specify Which Members are Tested for Concurrency Conflicts (LINQ to SQL).
Here I excluded all DateTime fields to be tested for Concurrency Conflict and the exception stopped from occurring again.
- In the try/catch block of your call to SubmitChanges, specify at what point you want exceptions to be thrown.
For more information, see How to: Specify When Concurrency Exceptions are Thrown (LINQ to SQL).
- Determine how much conflict detail you want to retrieve, and include code in your try/catch block accordingly.
For more information, see How to: Retrieve Entity Conflict Information (LINQ to SQL) and How to: Retrieve Member Conflict Information (LINQ to SQL).
- Include in your try/catch code how you want to resolve the various conflicts you discover.
For more information, see How to: Resolve Concurrency Conflicts by Retaining Database Values (LINQ to SQL), How to: Resolve Concurrency Conflicts by Overwriting Database Values (LINQ to SQL), and How to: Resolve Concurrency Conflicts by Merging with Database Values (LINQ to SQL).