1

How should I solve simulation update, when one user updates already updated entery by another user?

First user request 'Category' entityobject, second user does the same.
Second user updates this object and first user updates.

I have field timestamp field in database that wa set to Concurrency Mode - Fixed.

This is how I update:

public class CategoriesRepository : BaseCategoryRepository
{

     public  void Update(....)
    {
    try
     {
          Category catToUpdate = (from c in Contentctx.Categories where c.CategoryID == categoryId select c).FirstOrDefault();
          catToUpdate.SectionReference.EntityKey = new System.Data.EntityKey("ContentModel.Sections", "SectionID", sectionId);

          if (catToUpdate != null)
          {
               //Set fields here....
              Contentctx.SaveChanges();
          }

          base.PurgeCacheItems(CacheKey);
    }

    catch (OptimisticConcurrencyException ex)
    {

             }
    }

}
//Contentctx comes from base class: Contentctx:  
private ContentModel _contenttx;
        public ContentModel Contentctx
        {
            get
            {
                if ((_contenttx == null))
                {                   
                    _contenttx = new ContentModel();
                }

                return _contenttx;
            }
            set { _contenttx = value; }
        }



//on Business layer:
using (CategoriesRepository categoriesRepository = new CategoriesRepository())
{
            categoriesRepository.UpdateCategory(.....);
}

Exception never jumps...
How should I handle this?

1

1 Answer 1

1

Are you sure that sequence of calls is performed as you described? Anyway the main problem here is that you should not use the timestamp returned by the query in Upate method. You should use timestamp received when user get initial data for update. It should be:

  • User requests data from update - all fields and timestamp are received from DB
  • Timestamp is stored on client (hidden field in web app)
  • User modifies data and pushes Save button - all data including old timestamp are send to processin
  • Update method loads current entity
  • All updated fields are merged with old entity. Timestamp of entity is set to timestamp received in the first step.
  • SaveChanges is called

The reason for this is that it can pass a lot of time between first call and update method call so there can be several changes already processed. You have to use initial timestamp to avoid silent overwritting other changes.

Edit:

// You are updating category - update probably means that you had to load category
// first from database to show actual values. When you loaded the category it had some 
// timestamp value. If you don't use that value, any change between that load and c
// calling this method will be silently overwritten.
public void Update(Category category)     
{     
    try      
    {           
        Category catToUpdate = (from c in Contentctx.Categories where c.CategoryID == categoryId select c).FirstOrDefault();           
        ...           

        // Now categoryToUpdate contains actual timestamp. But it is timestamp of
        // actual values loaded now. So if you use this timestamp to deal with 
        // concurrency, it will only fire exception if somebody modifies data 
        // before you call SaveChanges few lines of code bellow.

        if (catToUpdate != null)           
        {                
            //Set fields here....  

            // To ensure concurrency check from your initial load, you must 
            // use the initial timestamp.           
            catToUpdate.Timestamp = category.Timestamp;
            Contentctx.SaveChanges();           
        }

        ...
    }      
    catch (OptimisticConcurrencyException ex)     
    {               
        ...
    }     
} 
Sign up to request clarification or add additional context in comments.

9 Comments

what do you mean I shouldnot use the timestamp returend by the query? I am not using it... EF should handle automatically isn't it (the Concurrency Mode - Fixed.)? And what do I do with the Timestamp I stored?
What are you doing in // Set fields here ...? Do you set timestamp as well? Timestamp fixed only means that EF will add timestamp into where condition of update sql statement.
So that is probably the problem. Because your Update method loads actual timestamp and use it for update = no change detected.
I lost you :(, what should I do to prevent updating already "updated" value? Can EF handle it for me or I must inmplement it by myself?
the signature of update is not public void Update(Category category), Category category is not the parameter i pass, i pass actual values to this method (without timestamp)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.