Saturday, May 28, 2011

Entity Framework's Concurrency Handling using Sql Server's rowversion field. And why modal dialog is bad for editing records

The Model:

public class Product
{
 [Key]
 public int ProductId { get; set; }
 public string ProductName { get; set; }
 public string WarehouseLocation { get; set; }
 public string LastAuditedBy { get; set; }
 public int Quantity { get; set; }

 [ConcurrencyCheck]
 public byte[] TheRowversion { get; set; }
}

The concurrent update scenario:

class Program
{
 static void Main(string[] args)
 {
  var userA = new CatalogContext();
  var userB = new CatalogContext();

  // User A and User B happen to open the same record at the same time
  var a = userA.Products.Find(1);
  var b = userB.Products.Find(1);

  
  
  a.ProductName = "New & Improved" + a.ProductName + "!";
     
  b.WarehouseLocation = "Behind appliances section";
  b.LastAuditedBy = "Linus";
  b.Quantity = 7;

  

  userA.SaveChanges();

  // This will fail. As the rowversion of the same record since it was first loaded, had 
  // already changed (the record was changed by User A first) when it's User B's time to save the same record.
  userB.SaveChanges();

}



Why a modal dialog is bad for editing a record? It's bad when you employ concurrency handling (a must) on records. Imagine your program is in kiosk mode, and let's say due to policy or technology constraints(say IE6), launching multiple instances of your app or using multiple tabs(e.g. IE6) isn't allowed/possible. How can we prevent User B from wasting his edits/time(imagine if there are 20 fields on a given record)? from losing his work? Let him open the latest changes of the record he happened to open at the same time with other users in a new tab(e.g. jQuery tab). With non-modal editing, User B can compare his changes against the latest changes of User A, and then he can copy-paste his changes to the latest changes, not much work will be wasted. You cannot facilitate this sort of thing with modal dialog editor, User B will be compelled to lose all his edits, and will just re-open the latest version from User A and re-input again all his concerning fields.


DDL:

create table Product
(
ProductId int identity(1,1) not null primary key,
ProductName nvarchar(100) not null unique,
WarehouseLocation nvarchar(100) not null,
LastAuditedBy nvarchar(100) not null,
Quantity int not null,
TheRowversion rowversion not null
) 

No comments:

Post a Comment