LINQ to SQL - "Row not found or changed" when updated using OnPropertyChanged

1.9k Views Asked by At

The Save method in the following code is failing with the error "Row not found or changed".

Question question = questionService.getQuestionById(id); 
// returning Context.Question.Where(q => q.id == id).SingleOrDefault()

question.Text = "some text";

questionService.Save(question); 
// Context.SubmitChanges();

Question is a DTO generated using CodeSmith and PLINQO templates. However, the "Row not found or changed" error only occurs aftering implementing a custom override to the OnPropertyChanged event to automatically insert when a record was created or modified. I profiled the queries that were generated, when the getQuestionById method is executed, it is executing a normal select statement. However, if the modified date is returned as '2012-07-28 12:15:00.900', when I attempt to save the record, the update is failing because it is adding Modified = '2012-07-28 12:15:00.903' to the update statement, which is a few milliseconds different from what exists in the database. So I know this has something to do with the following code added to the generated Question object:

protected override void OnPropertyChanged(string property)
{
    this.UpdateProperties(property);
    base.OnPropertyChanged(property);
}

public static void UpdateProperties(this object updatedObject, string property)
{
    if (property == created || property = modified) return;
    // prevents an infinite loop 

    Update(updateObject);
    // sets updatedObject.Created and updateObject.Modified fields
}

I have found a few posts that suggest setting the UpdateMode to never in the dbml for fields that use higher precision than seconds. I can use this as a last resort, but I have been adding the same code to other tables with the same data types for a while without any problems and would like to understand why it is only happening for this one table. This also seems to fail somewhat randomly, I don't have specific steps to reproduce it, but it does seem to happen more frequently when I am not debugging.

1

There are 1 best solutions below

2
On

My guess is you're using your Modified (and/or Created) column in the database to check for concurrency. You are also updating this column yourself. This mix is not correct.

A better way is to use a timestamp as the concurrency-check-column. This column will be set by SQL server (assuming this is what you are using), and is not a date-time but some internal unique database generated value.

Some googling gave me this article which I think will explain the basics well on how to set up your timestamp column.