Решение проблемы обновления оптимистичного параллелизма с помощью Entity Framework - PullRequest
1 голос
/ 15 января 2011

Как решить проблему обновления симуляции, когда один пользователь обновляет уже обновленную энтузиазм другим пользователем?

Первый пользовательский объект «Категория», объект, второй пользователь делает то же самое.
Второй пользователь обновляет этот объект, а первый пользователь обновляет.

У меня есть поле метки времени в базе данных, в котором установлен режим параллелизма - исправлено.

Вот как я обновляюсь:

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(.....);
}

Исключение никогда не переходит ...
Как мне справиться с этим?

1 Ответ

1 голос
/ 15 января 2011

Вы уверены, что последовательность вызовов выполняется так, как вы описали?В любом случае, основная проблема заключается в том, что вы не должны использовать метку времени, возвращаемую запросом в методе Upate.Вы должны использовать временную метку, полученную, когда пользователь получает начальные данные для обновления.Должно быть:

  • Пользователь запрашивает данные из обновления - все поля и метка времени получаются из БД
  • Метка времени сохраняется на клиенте (скрытое поле в веб-приложении)
  • Пользователь изменяет данные и нажимает кнопку Сохранить - все данные, включая старую временную метку, отправляются в процесс
  • Метод обновления загружает текущую сущность
  • Все обновленные поля объединяются со старой сущностью.Временная метка объекта установлена ​​на временную метку, полученную на первом шаге.
  • SaveChanges называется

Причина этого в том, что он может передавать много времени между первым вызовом и методом обновлениявызов, так что может быть несколько обработанных изменений.Вы должны использовать начальную временную метку, чтобы избежать перезаписи других изменений без вывода сообщений.

Редактировать:

// 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)     
    {               
        ...
    }     
} 
...