Row not found or changed LINQ C# error on simple s

2019-03-10 04:20发布

问题:

First of all, there is no chance that this is a multi-user issue, as I'm working locally on a dev version of the database.

I am getting the not very explanatory Row not found or changed error being thrown when I perform db.SubmitChanges(). If I break the execution just before the SubmitChanges() occurs, I can check in SQL Server Management Studio and the row does exist!

Here's the code for the whole function, just to put it in context for anyone who wants to help, but the problem line is right at the end (line 48).

Update This is a really odd one: the error is caused by updating matchingTrans.Url (see penultimate line of code). Commenting out this line doesn't throw the error - even if the matchingTrans.Title still gets updated.

private static void MenuItemUpdate(int languageId, NavigationItem item)
{
    using (var db = DataContextFactory.Create<MyDataContext>())
    {
        // Select existing menu item from database.
        var dbItem =
            (from i in db.MenuItems
             where i.Id == item.Id
             select i).Single();
        // Obtain ID of link type.
        dbItem.FkLinkTypeId = GetLinkTypeByName(
            Enum.GetName(typeof (NavigationItemLinkType), item.LinkType)).Id;
        // Update the Link field with what is given.
        dbItem.Link = item.Link;
        db.SubmitChanges();

        // Item already exists and needs editing.
        // Get associated translations.
        var trans =
            from t in db.MenuItemTranslations
            where t.FkMenuItemId == item.Id
            select t;

        // If translation exists for given language, edit it.
        var matchingTrans =
            (from t in trans
             where t.FkLanguageId == languageId
             select t).SingleOrDefault();

        if (matchingTrans == null)
        {
            // No matching translation - add one.
            var newDbTrans = new MenuItemTranslation
            {
                FkMenuItemId = item.Id,
                FkLanguageId = languageId,
                Title = item.Title,
                Url = item.FriendlyUrl
            };
            db.MenuItemTranslations.InsertOnSubmit(newDbTrans);
            db.SubmitChanges();
        }
        else
        {
            // Matching translation - edit it.
            matchingTrans.Title = item.Title;
            matchingTrans.Url = item.FriendlyUrl;
            db.SubmitChanges();
            // WTF ERROR: Row not found or changed.
        }
    }
}

回答1:

Looking at the SQL Profiler output, it helped me figure out the answer to this. There was a bad piece of SQL being generated which ended with WHERE 0 = 1 ... an obvious error.

It turns out that the field had simply been changed to allow nulls by another developer, and the Linq-to-SQL file hadn't been updated accordingly.

In short, if the Row not found or changed error message appears to be generated for no reason, make sure your database schema exactly matches your .dbml file else you'll get this error message on any fields that have slightly differing schemas.



回答2:

Take a look at the connection property "No Count" at sql server server level

1. Right click on Sql server connection in Object Explorer -->Property
2. Go to Connection Tab/Page
3. Look for the Default connection option "no count"
4. Make sure this option is not checked.



回答3:

Another possibility that I've found to add to the excellent list of answers here:

When using a not-nullable column in a database - then mapping that to a datatype that is intrinsically nullable (in this example DB type is LONG BLOB NOT NULL mapped to a byte array in c#) you can end up in a situation where updating the database with the exact same byte array causes this error to be thrown.

Example: You have a website that allows the user to upload an image to the database. Your table has a blob (image in sql server, whatever) that is not nullable. The user chooses to update the record with the exact same image that is already there. The update check will fail. I fixed this by first doing a .SequenceEqual() check and then only calling .SubmitChanges() on the context object if the incoming byte array was not equal to the existing one.



回答4:

I had this issue even when the database schema and dbml matched exactly. The issue was I was trying to change an entity and insert entities in a single SubmitChanges statement. I fixed it by doing SubmitChanges on each operation instead of all at once.

This was all in a transaction scope so that may have something to do with it but I'm not sure.