Jul 28 2007

Optimistic Concurrency in DLinq

Category: DLinq | LinqBil@l @ 17:26

Dlinq handles optimistic concurrency implicitly when exexuting SubmitChanges() method. However, you can handle the resolution of the conflict and deciding on how to solve a conflict that happened.

Usually, when two users retrieve the same record, one of them updates the record and submit changes, then anotehr user comes in and performs another update, here the conflict is detected.
Here is an example:

    Product product = db.Products.First(p => p.ProductID == 1);
   

    // Open a second connection to the database to simulate another user
    // who is going to make changes to the Products table               
    Northwind otherUser_db = new Northwind(connString) { Log = db.Log };
    Product otherUser_product = otherUser_db.Products.First(p => p.ProductID == 1);
    otherUser_product.UnitPrice = 999.99M;
    otherUser_product.UnitsOnOrder = 10;
    otherUser_db.SubmitChanges();


    // first user re-updates the UnitPrice
    product.UnitPrice = 777.77M;

    bool conflictOccurred = false;
    try {
        db.SubmitChanges(ConflictMode.ContinueOnConflict);
    } catch (OptimisticConcurrencyException ex) {
        Console.WriteLine("* * * OPTIMISTIC CONCURRENCY EXCEPTION * * *");
        foreach (OptimisticConcurrencyConflict aConflict in ex.Conflicts) {
            Product prod = (Product)aConflict.Object;
            Console.WriteLine("The conflicting product has ProductID {0}", prod.ProductID);
            Console.WriteLine();
            Console.WriteLine("Conflicting members:");
            Console.WriteLine();
            foreach (OptimisticConcurrencyMemberConflict memConflict in aConflict.GetMemberConflicts()) {
                string name = memConflict.MemberInfo.Name;
                string yourUpdate = memConflict.CurrentValue.ToString();
                string original = memConflict.OriginalValue.ToString();
                string theirUpdate = memConflict.DatabaseValue.ToString();
                if (memConflict.HaveModified) {
                    Console.WriteLine("'{0}' was updated from {1} to {2} while you updated it to {3}",
                                      name, original, theirUpdate, yourUpdate);
                } else {
                    Console.WriteLine("'{0}' was updated from {1} to {2}, you did not change it.",
                        name, original, theirUpdate);
                }
            }
            Console.WriteLine();
        }
        conflictOccurred = true;
    }


The above example shows how the conflict is detected and displays a detailed information on all the conflicting members.

Inside the catch statement, we can resolve the conflict as follows:


RefreshMode.OverwriteCurrentValues
-------------------------------------
catch (OptimisticConcurrencyException ex) {
        ex.Resolve(RefreshMode.OverwriteCurrentValues);
        db.SubmitChanges();
    }

With OverwriteCurrentValues, the second user who tried to update the record, his/her update will be disgarded and the record in the database will be maintained!


RefreshMode.KeepCurrentValues
-------------------------------------
catch (OptimisticConcurrencyException ex) {
        ex.Resolve(RefreshMode.KeepCurrentValues);
        db.SubmitChanges();
    }

With KeepCurrentValues, the second user will override any changes in the database record done by the first user. Any column that the second update didn't change, it will preserve its original data from the database and not from the update done by the first user if any.


RefreshMode.KeepChanges
-------------------------------------
catch (OptimisticConcurrencyException ex) {
        ex.Resolve(RefreshMode.KeepChanges);
        db.SubmitChanges();
    }

With KeepChanges, the second user will override any changes in the database record done by the first user. Any column that the second update didn't change, it will be assigned the value that was updated by the first user.


Hope this post really helps you. I want to post this to make sure I have a small post as reference to keep myself on the safe side not to forget it!!

Regards

Tags: ,

Comments are closed