Skip to main content

LINQ To SQL Row not found or changed

LINQ To SQL likes to use TimeStamp columns for version tracking and makes it really easy to do so. However, in a lot of the apps I work on, we need to keep track of when the last change was made so we have a DateTime column titled LastUpdated. Using Steve Michelotti's post, I was able to use this column for row version control.

Everything was fine until I was using a DetailsView and got the message "Row not found or changed". This message is LINQ's way of telling you that the row has been changed and you now have a concurrence conflict. Since I was working on my local box, I knew this wasn't the case. Pulling up SQL Profiler, I was able to see that LINQ was sending the LastUpdated date back without milliseconds. Since this isn't the same as the value on the row, it thinks a change has occurred.

I was displaying the LastUpdated field in a readonly column so it shouldn't have been getting changed. I also had it as DataKey and could see that it was getting passed back. After farting around for a while, I finally figured out that it was the Label control in the EditItemTemplate that was causing the problem.

<asp:Label ID="Label3" runat="server" Text='<%# Bind("LastUpdated") %>'></asp:Label>

The Bind in the above causes the DetailsView to use the value displayed in the label as the value for the update. Bind is two way even though the column is marked ReadOnly and ReadOnly really means "Don't let the user change anything." It doesn't mean "Don't let the value change."

Simply changing the Bind to Eval solves the problem as below.

<asp:Label ID="Label1" runat="server" Text='<%# Eval("LastUpdated") %>'></asp:Label>

I haven't tested but this should affect all of the other controls such as GridView and FormView.

Cheers

Comments

Treespace said…
I don't see any harm in adding a separate Version column of type Timestamp, and then separate Created and Modified columns.
James said…
Oh man, this has been driving me MAD. Thank you for the post!

Popular posts from this blog

Migrating Legacy Apps to the New SimpleMembership Provider

Asp.Net MVC4 uses the new SimpleMembership provider, changes the table structure and adds a new hashing algorithm. The reasons for the changes can be found in this article by Jon Galloway. This article shows how to migrate your existing apps to the new provider.I’m assuming that you stored your passwords in the unrecoverable SHA-1 format. If you didn’t, then you’ll have to change a couple of things. All of my apps are done this way so… I’m also assuming that you have created the basic skeleton of the new app and ran it once so the correct tables will be created.First, we’ll look at the new tables. Previously, we had all of those aspnet_xxxxxx tables. Here’s the new ones.UserProfileContains all of the elements relevant to the user. This is a combination of the aspnet_Users table and the aspnet_Profiles table.webpages_MembershipStores the password info when not using OAuth, Live, Facebook, etc. This table is somewhat of a match to the aspnet_Membership table.webpages_OAuthMembershipStor…

JavaScript function to automatically add slashes to date

In converting an old Windows app to a browser app, the user wanted to be able to enter dates without the slashes. Here's a simple jscript: 1:// Function to convert short date string (MMddyy) 2:// or (MMddyyyy) to a date string (mm/dd/yyyy). 3:// txtBox is the actual textbox control 4:// with the value to be processed. 5:function FixShortDate(txtBox) { 6:if (txtBox == null) { 7:return'' } 8: 9:var re = new RegExp(/(\d{6})(\d{2})?/); 10: 11:if (re.test(txtBox.value)) 12: { 13:if (txtBox.value.length == 8) { 14: txtBox.value = txtBox.value.substring(0, 2) + '/' + txtBox.value.substring(2, 4) + '/' + txtBox.value.substring(4, 8) 15: } 16: 17:if (txtBox.value.length == 6) { 18:if (txtBox.value.substring(4, 6) < 20)