tags:

views:

145

answers:

5

This is concurrency related. So the SubmitChanges() fails, and a ChangeConflictException is thrown. For each ObjectChangeConflict in db.ChangeConflicts, its Resolve is set to RefreshMode.OverwriteCurrentValues? What does this mean?

http://msdn.microsoft.com/en-us/library/bb399354.aspx

Northwnd db = new Northwnd("...");
try
{
    db.SubmitChanges(ConflictMode.ContinueOnConflict);
}

catch (ChangeConflictException e)
{
    Console.WriteLine(e.Message);
    foreach (ObjectChangeConflict occ in db.ChangeConflicts)
    {
        // All database values overwrite current values.
        occ.Resolve(RefreshMode.OverwriteCurrentValues);
    }
}
A: 

I think it means that if it detects a conflict, see this under computing science, then it goes into the catch. Within there it goes through each of the conflicts (the foreach loop) and resets the values to what they were before the change tried to occur.

Kyra
A: 

Apparently, any changes you've done to the objects are to be thrown out, since somebody else has stolen a march on you and updated the database while you were busy. In optimistic concurrency, dropping the changes is the only possible automated solution. However, the user probably isn't going to be too happy if they spent any time on inputting the discarded data.

Pontus Gagge
+8  A: 

I added some comments to the code, see if it helps:

Northwnd db = new Northwnd("...");
try
{
    // here we attempt to submit changes for the database
    // The ContinueOnConflict specifies that all updates to the 
    // database should be tried, and that concurrency conflicts
    // should be accumulated and returned at the end of the process.
    db.SubmitChanges(ConflictMode.ContinueOnConflict);
}

catch (ChangeConflictException e)
{
    // we got a change conflict, so we need to process it
    Console.WriteLine(e.Message);

    // There may be many change conflicts (if multiple DB tables were
    // affected, for example), so we need to loop over each
    // conflict and resolve it. 
    foreach (ObjectChangeConflict occ in db.ChangeConflicts)
    {
        // To resolve each conflict, we call
        // ObjectChangeConflict.Resolve, and we pass in OverWriteCurrentValues
        // so that the current values will be overwritten with the values
        // from the database
        occ.Resolve(RefreshMode.OverwriteCurrentValues);
    }
}
dcp
A: 

The conflict is propabely caused by the fact that the object in your datacontext (the object that stores and keeps changes etc in .net code) has other values then the ones in your db.

Let's say you load a person object from the db. One of the fields is firstname, firstname is S oo. Now you have a copy of your record in the datacontext. You change some things and want to write the changes to the db, but when (LINQ? other orm) wants to write the changes to the DB, it notices that the firstname in the DB is already changed.

So someone/something has changed your record, you have kind of a "deadlock" (correct term?) then you have to define what is more important, your changes, or the changes that something/someone else made.

TO THE POINT !!! -> Refreshmode.overwirteCurrentValues Just refreshes the object in your datacontext, it RELOADS the object from the db so that you are working with the updated object.

I hope this was a little clear :)

grtz

Nealv
A: 

First, you must understand that LinqToSql tracks two states for each database row. The original state and the current state. Original state is what the datacontext thinks is in the database. Current state has your in-memory modifications.

Second, LinqToSql uses optimistic concurrency to perform updates. When SubmitChanges is called, the datacontext sends the original state (as a filter) along with the current state into the database. If no records are modified (because the database's record no longer matches the original state), then a ChangeConflictException is raised.

Third, to resolve a change conflict, you must overwrite the original state so the optimistic concurrency filter can locate the record. Then you have to decide what to do with the current state... You can abandon your modifications (that's what the posted code does), which will result in no change to the record, but you are ready to move on with the current database values in your app.

David B