解决实体框架的乐观并发更新问题 [英] Solving Optimistic Concurrency Update problem with Entity Framework

查看:88
本文介绍了解决实体框架的乐观并发更新问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果一个用户更新其他用户更新的文件,我应该如何解决模拟更新?

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.

这是我如何更新:

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?

推荐答案

您是否确定按照您所描述的方式执行呼叫序列?无论如何,这里的主要问题是您不应该使用Upate方法中查询返回的时间戳。您应该使用用户获取初始数据进行更新时收到的时间戳。应该是:

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:


  • 用户从更新请求数据 - 从DB接收所有字段和时间戳

  • Timestamp存储在客户端(网络应用程序中的隐藏字段)

  • 用户修改数据并按下保存按钮 - 包括旧时间戳的所有数据都将发送到processin

  • 更新方法加载当前实体

  • 所有更新的字段都与旧实体合并。

  • SaveChanges被调用

  • 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.

编辑:

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

这篇关于解决实体框架的乐观并发更新问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆