views:

266

answers:

1

I am trying to implement Optimistic Locking in an asp.net MVC application, as well as provide audit trailing.

The audit framework relies on being able to call DataContext.GetModifiedMembers during SubmitChanges, which makes good sense, i guess.

The optimistic locking uses ROWVERSION timestamps, serialized to base64 and put in a hidden field in the view.

My Edit action looks like this:

[AcceptVerb(HttpVerb.Post)] 
public ActionResult Edit(MyType myType)
{ 
   context.MyTypes.Attach(myType, true);
   context.SubmitChanges(ConflictMode.FailOnFirstConflict);
}

When doing this, the DataContext.GetModifiedMembers will always return ALL the properties on MyType, rather than just the ones that are changed between the database and the values provided, which breaks the auditing. Specifically it returns every property as having been changed from their new value to their new value, so its not even like I can do anything clever to the list.

I tried loading the object first, before attaching it, but this gives a duplicate key exception.

I then tried using UpdateModel, i.e.

[AcceptVerb(HttpVerb.Post)] 
public ActionResult Edit(int id, FormCollection col)
{ 
   var mt = context.MyTypes.Single( mt =>  mt.id = id);
   UpdateModel(mt);
   context.SubmitChanges(ConflictMode.FailOnFirstConflict);
}

This works with the auditing, but fails the optimistic locking. Rather than a ChangeConflictException i get an InvalidOperationException because the UpdateModel is changing the concurrentTS field (which apparently is readonly).

What am I doing wrong?

A: 

Progress so far consists of doing the last part, and catching InvalidOperationException and looking for the text "Value of member 'ConcurrencyTimestamp'", and rethrowing that as a ChangeConflictException.

That seems to do the trick, but it is not pretty.

Soraz