1

I'm investigating an intermittent occurrence of Devart.Data.Linq.ChangeConflictException: Row not found or changed.

I've been reading the Devart article on concurrency conflicts, and just as a starting point I am trying to reproduce a concurrency conflict. Using the included MS-based LINQ classes this is easy to do (using the code structure below does so successfully). However even following their example in the article I can't produce an exception. I have tried

  • Using both an ADO paramaterised query exactly as shown in their article
  • Using the simplified ADO query shown below (not worried about injection attacks during this test)
  • Using LinqConnect with a new context (also suggested in their article).
  • Pausing execution with a debugger and manually updating table using MySQL Workbench.

This is the test code I am using:

public static void MySqlTest()
{
    using (MySqlDataContext db = new MySqlDataContext())
    {
        Customer customer = db.Customers.First(c => c.Username.Equals("ian2"));

        MySqlAdoChange(db.Connection);
        //MySqlLinqConnectChange();

        customer.Address1 = "Original change" + DateTime.UtcNow.Ticks;
        db.SubmitChanges();
    }
}

public static void MySqlAdoChange(DbConnection connection)
{
    connection.Open();
    var command = connection.CreateCommand();
    command.CommandText = "UPDATE customers SET Address1 = 'Conflicting change" + DateTime.UtcNow.Ticks + "' WHERE Username = 'ian2'";
    command.ExecuteNonQuery();
}

public static void MySqlLinqConnectChange()
{
    using (MySqlDataContext db = new MySqlDataContext())
    {
        Customer customer = db.Customers.First(c => c.Username.Equals("ian2"));
        customer.Address1 = "Conflicting change" + DateTime.UtcNow.Ticks;
        db.SubmitChanges();
    }
}

What is doubly-strange is that the value saved to the database alternates between the two! I had to append DateTime ticks on to the end to ensure uniqueness, otherwise it was optimising away my update, and only updating to become the value that wasn't currently active.

Can anyone explain this behaviour? Why can't I produce a ChangeConflictException?

Community
  • 1
  • 1
Ian
  • 1,475
  • 2
  • 15
  • 31

1 Answers1

1

First note that in your example code, you update Phone field in MySqlTest function, but Address1 field in MySqlAdoChange function, so there cannot be any conflict.

However, most likely even if you correct this you won't have update conflict anyway. If you look at your Customer class source code, at Phone property, you (most likely) will see it is decorated with Column attribute with UpdateCheck = UpdateCheck.Never (which is the default: see here https://www.devart.com/linqconnect/docs/MemberMapping.html). So by default, LinqConnect won't check for update conflicts for your fields, unless you tell it which fields to check by decorating them with UpdateCheck = UpdateCheck.Always or UpdateCheck.WhenChanged. Of course you should not modify source code directly but instead change that property in model designer.

Evk
  • 98,527
  • 8
  • 141
  • 191
  • You're right of course about the Phone vs Address. Originally I was testing on the Phone field (which is actually a text field, but not obviously so), then I decided to use Address to "simplify" things, and didn't update the SO question correctly. I will look into the attribute you suggest, thanks for the info. I have another bounty question [here](http://stackoverflow.com/questions/36586779/devart-changeconflictexception-but-values-still-written-to-database?lq=1) which you might be interested in, this one is just a subset of the larger problem. – Ian Apr 26 '16 at 22:54
  • You were spot-on twice, my variables were _all_ (barring ID PKs) decorated with `UpdateCheck = UpdateCheck.Never` attribute. And removing it generates an exception as expected. Thank you very much, that solves half my problem. But it now makes my other `ChangeConflictException` issue even more puzzling. – Ian Apr 26 '16 at 23:27