并发管理实战

 玩具模型     |      2019-12-19 11:07

4.3 当爆发多少现身时,保留末了(最新:最终一回卡塔尔(英语:State of Qatar)输入的多少

要注脚输入对象的质量,必得先把该属性的 ConcurencyMode 设置为 Fixed,那样系统就能够实时检验对象属性的输入值 。
当该属性被同一时间创新,系统便会激起 OptimisticConcurrencyException 非常。捕获该非常后,能够利用 ObjectContext.Refresh (RefreshMode,object卡塔尔刷新上下文中该目的的气象,当 RefreshMode 为 ClientWins 时,系统将会保持内外文中的几天前有多少,即保留最新输入的靶子值。那个时候再选用ObjectContext.SaveChanges, 系统就能把最新输入的对象值参预数据库在那之中。

在底下的例子当,系统运转前先把 Person 的 FirstName、SecondName 多个天性的 ConcurencyMode 属性设置为Fixed,使系统能监视那多少个属性的变动。所输入的数量只在FirstName、SecondName 四个值中作出改革。在数额交由前先以 DisplayProperty 方法显示数据库最先的数码属性,在数据初次更新后再也调用 DisplayProperty 呈现更新后的多少属性。在第三遍改正数据时,由调用ObjectContext.SaveChanges时,数据库中的数据已经被修改,与当前上下文ObjectContext 的数量存在冲突,系统将激情OptimisticConcurrencyException 十分,当时把吸引那多少个的对象属性再次呈现出来。对非常进行拍卖后,呈现数据库中最终的靶子值。

钱柜qg999娱乐官网, 

 

观测测量试验结果,可以预知当RefreshMode状态为ClientWins时,系统将会保留上下文个中的指标属性,使用此情势能够在发出并发至极时保持最新输入的对象属性。

 

生机勃勃、并发相关概念

并发的项目:

首先种情势称为悲观式并发,即当三个客户已经在修正某条记下时,系统将谢绝别的客商同不平时间修正此记录。
其次种方式称为乐观式并发,即系统允许三个客商同期修正同一条记下,系统会事前定义由数量现身所引起的产出卓殊管理格局,去处理修正后只怕产生的矛盾。常用的乐观性并发管理办法有以下二种:

    1、保留最终改进的值。
    2、保留最先改良的值。
    3、合併往往改进的值。

4.4 当发生多少现身时,保留最初(最先:最先二遍)输入的数据

把目标属性的 ConcurencyMode 设置为 Fixed 后,同时修正该属性,将会激发 OptimisticConcurrencyException 卓殊。那时应用 ObjectContext.Refresh (RefreshMode,object卡塔尔(英语:State of Qatar) 刷新上下文中该目的的气象,当 RefreshMode 为 StoreWins 时,系统就可以把数据源中的数据代表上下文中的多寡。
因为初次调用 SaveChanges,数据能够成功保存到数据库。可是在 ObjectContext 并未有释放时,再一次利用 SaveChanges 异步更新数据,就能吸引OptimisticConcurrencyException 并发卓殊。当 RefreshMode 为 StoreWins 时,系统就能够保留初次输入的数目属性。
此例子与地点的例子十分相近,只是把 RefreshMode 改为 StoreWins 而已。在作业逻辑较为复杂的的系统当中,提出选拔此措施管理并发非凡。在保留最先输入的多少校正属性后,把属性返还给客商,让客户进行比较后再决定下一步的管理格局。

钱柜qg999娱乐官网 1

钱柜qg999娱乐官网 2

 

考查测量检验结果,可知当 RefreshMode 状态为 StoreWins 时,系统将会以数据源中的数据代表上下文个中的靶子属性。在作业逻辑较为复杂的的系统在那之中,提议采取此措施管理并发非凡。


链接: 密码: fyb3

演练的源码,有改过的荒诞的爱侣记得分享

四、乐观并发

为了缓慢解决消极并发所拉动的主题素材,ADO.NET Entity Framework 提供了一发便捷的开阔并发管理方式。相对于LINT to SQL , ADO.NET Entity Framework 简化了无牵无挂并发的管理格局,它能够灵活运用归拢量据、保留初次输入数据、保留最新输入数据(3种艺术卡塔尔国等办法管理并发冲突。

二、模型属性的现身管理选项

正如图模型设计器中TimeStamp字段为启用并发

钱柜qg999娱乐官网 3

<EntityType Name="UserAccout">
          <Key>
            <PropertyRef Name="Id" />
          </Key>
          <Property Name="Id" Type="Int32" Nullable="false" annotation:StoreGeneratedPattern="Identity" />
          <Property Name="FirstName" Type="String" Nullable="false" />
          <Property Name="LastName" Type="String" Nullable="false" />
          <Property Name="AuditFileds" Type="OrderDB.AuditFields" Nullable="false" />
          <Property Name="Timestamp" Type="DateTime" Nullable="false" ConcurrencyMode="Fixed" annotation:StoreGeneratedPattern="Computed" />
        </EntityType>

现身情势:ConcurencyMode 有多少个分子:

None : 在写入时从没验证此属性。 那是暗中认可的现身方式。

Fixed: 在写入时平昔验证此属性。

当模型属性为暗许值 None 时,系统不会对此模型属性实行检查评定,当同三个小时对此属性举行退换时,系统会以数量统一情势管理输入的属性值。

当模型属性为Fixed 时,系统会对此模型属性举行质量评定,当同贰个年华对品质进行改善时,系统就能够激起OptimisticConcurrencyException 至极。

 

4.1 以统一方式管理并发数据

小结:当模型属性的 ConcurencyMode 为暗中认可值 None ,一旦同四个目的属性同不经常候被改换,系统将以统风姿罗曼蒂克数据的章程管理并发冲突,这也是 Entity Framework 处理并发矛盾的暗许情势。

集结管理模式如下:

(1)当同一时间针对同四个对象属性作出修正,系统将保存最新输入的属性值。

(2)当同期对同意气风发对象的不等属性作出修正,系统将保存已被退换的属性值。下面用八个例证作出表达:

钱柜qg999娱乐官网 4

运作结果:

钱柜qg999娱乐官网 5

#region (4.1)测试不设置任何并发测试时,当产生并发EF的处理方法
        delegate void MyDelegate(Address addressValue);
        public  StringBuilder sb = new StringBuilder();
        public Address GetAddress(int id)
        {
            using (OrderDBContainer context = new OrderDBContainer())
            {
                IQueryable<Address> list = context.AddressSet.Where(x => x.Id == id);
                return list.First();
            }
        }
        /// <summary>
        /// 修改方法
        /// </summary>
        /// <param name="addressValue"></param>
        public void UpdateAddress(Address addressValue)
        {
            using (OrderDBContainer context = new OrderDBContainer())
            {
                //显示输入新数据的信息
                Display("Current", addressValue);
                var obj = context.AddressSet.Where(x => x.Id == addressValue.Id).First();
                if (obj != null)
                    context.Entry(obj).CurrentValues.SetValues(addressValue);
                //虚拟操作,保证数据能同时加入到上下文当中
                Thread.Sleep(100);
                context.SaveChanges();
            }
        }        
        /// <summary>
        /// 显示实体当前属性
        /// </summary>
        /// <param name="message"></param>
        /// <param name="addressValue"></param>
        public void Display(string message, Address addressValue)
        {
            String data = string.Format("{0}n  Address Message:n    Id:{1}  Address1:{2}  " +
                "address2:{3} rn ",
                message, addressValue.Id, addressValue.Address1, addressValue.Address2 );
            sb.AppendLine(data);
        }     

        /// <summary>
        /// (1)测试使用EF默认的机制,当配置并发控制时,系统是使用的合并的方式
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            //在更新数据前显示对象信息
            var beforeObj = GetAddress(1);
            Display("Before", beforeObj);

            //更新Person的SecondName,Age两个属性
            Address _address1 = new Address();
            _address1.Id = 1;
            _address1.Address1 = "古溪";
            _address1.Address2 = beforeObj.Address2;
            _address1.AuditFields.InsertDate = beforeObj.AuditFields.InsertDate;
            _address1.AuditFields.UpdateDate = beforeObj.AuditFields.UpdateDate;
            _address1.City = beforeObj.City;
            _address1.Zip = beforeObj.Zip;
            _address1.State = beforeObj.State;

            //更新Person的FirstName属性
            Address _address2 = new Address();
            _address2.Id = 1;
            _address2.Address1 = beforeObj.Address1;
            _address2.Address2 = "江苏";
            _address2.AuditFields.InsertDate = beforeObj.AuditFields.InsertDate;
            _address2.AuditFields.UpdateDate = beforeObj.AuditFields.UpdateDate;
            _address2.City = beforeObj.City;
            _address2.Zip = beforeObj.Zip;
            _address2.State = beforeObj.State;

            //使用异步方式同时更新数据
            MyDelegate myDelegate = new MyDelegate(UpdateAddress);
            myDelegate.BeginInvoke(_address1, null, null);
            myDelegate.BeginInvoke(_address2, null, null);

            Thread.Sleep(1000);
            //在更新数据后显示对象信息
            var afterObj = GetAddress(1);
            Display("After", afterObj);
            this.textBox1.Text = sb.ToString();
        }

        /// <summary>
        /// 先插入几条数据等着测试
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnSaveAddress_Click(object sender, EventArgs e)
        {
            using (OrderDBContainer db = new OrderDBContainer())
            {
                Address address = new Address();
                address.Address1 = "古溪镇";
                address.Address2 = "安镇";
                address.State = "2";
                address.City = "无锡";
                address.AuditFields.InsertDate = DateTime.Now;
                address.AuditFields.UpdateDate = DateTime.Now;
                address.Zip = "21415";
                db.AddressSet.Add(address);
                db.SaveChanges();
            }
        }

        /// <summary>
        /// 还原成初始值,准备再次测试
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button5_Click(object sender, EventArgs e)
        {
            using (OrderDBContainer db = new OrderDBContainer())
            {
                Address _address = db.AddressSet.Where(x => x.Id == 1).First();
                _address.Address1 = "aaa";
                _address.Address2 = "bbb";
                db.SaveChanges();
            }
        }
        #endregion

备考:实践进度中相遇的标题

在八十六线程中EF更改事件的消除方案,使用attach不能:

钱柜qg999娱乐官网 6

使用Entry也报错

钱柜qg999娱乐官网 7

聊起底仿照效法如下帖子

钱柜qg999娱乐官网 8

/// <summary>
        /// 修改方法
        /// </summary>
        /// <param name="addressValue"></param>
        public void UpdateAddress(Address addressValue)
        {
            using (OrderDBContainer context = new OrderDBContainer())
            {
                //显示输入新数据的信息
                Display("Current", addressValue);
                var obj = context.AddressSet.Where(x => x.Id == addressValue.Id).First();
                if (obj != null)
                    context.Entry(obj).CurrentValues.SetValues(addressValue);
                //虚拟操作,保证数据能同时加入到上下文当中
                Thread.Sleep(100);
                context.SaveChanges();
            }
        }

引用:“以联合数据的法门管理并发冲突尽管方便快节,但在事情逻辑较为复杂的系统下并不相符利用此管理格局。比如在广阔的Order、OrderItem的报表中,OrderItem 的单价,数量会直接影响Order的完好价格,这样使用合并的数量据的方法管理并发,有希望引起逻辑性的谬误。那个时候,应该思索以此外方法处理并发冲突。”。

任何什么艺术吧?【待补充】

 

4.1 去除与立异操作同偶尔间运维(非框架自动管理手艺,开荒自动改进意况手动扩张的)**

Entity Framework 能以完美的机制灵活处理同期更新同朝气蓬勃对象的操作,但只要删除操作与修正操作同期运转时,就恐怕存在逻辑性的特别。

举例:七个客户端相同的时候加载了同一个指标,第四个顾客端更新了数额后,把多少重复提交。但在交付前,第贰个客商端已经把数据库中的本来就有数量删除。

那儿,上下文中的靶子处于区别的图景下,将会吸引OptimisticConcurrencyException 卓殊(ObjectContext 与DBContext二种办法下,极度不一样等,具体要基于测量试验结果自己判定)。
遇见此卓绝时,能够用 try(OptimisticConcurrencyException){...} catch {...} 方式养虎遗患非常,然后改成对象的State 属性。把EntityState 校正为 Added ,被去除的多少便会被再度加载。若把 EntityState 修正为 Detached 时,数据便会被顺顺当当删除。下边把指标的 EntityState 属性改进为 Added 作为例子。

钱柜qg999娱乐官网 9

代码如下:管理结果前后ID变化了(恐怕那正是某些布局师使用手动创造的GUID的不二等秘书技,而不行使自增的案由之黄金时代吧,因为数量删除后再创立就回不到从前的ID了,不是太灵活,使用GUID再组成数据版本(dataVison)字段,timeStamp基本上调控数据的面世已经足足啊。

//更新对象
        public int UpdateWithConcurrent(int num, Address addressValue)
        {
            int returnValue = -1;
            using (OrderDBContainer context = new OrderDBContainer())
            {
                var obj = context.AddressSet.Where(x => x.Id == addressValue.Id).First();
                //显示对象所处状态
                DisplayState("Before Update", obj);
                try
                {
                    if (obj != null)
                        context.Entry(obj).CurrentValues.SetValues(addressValue);
                    //虚拟操作,保证数据已经在数据库中被异步删除
                    Thread.Sleep(300);
                    context.SaveChanges();
                    returnValue = obj.Id;
                }
                catch (Exception)
                {
                    //针对异常要做相应的判断,因为我只测试了删除的情况,就写死直接修改成Added 了
                    //正确的是要区分到底是修改还是删除  OptimisticConcurrencyException ex
                    //把对象的状态更改为 Added
                    context.Entry(obj).State = System.Data.Entity.EntityState.Added;
                    context.SaveChanges();
                    returnValue = obj.Id;
                }
            }
            return returnValue;
        }

并发时的非常类型:

钱柜qg999娱乐官网 10

ID发生了更改

钱柜qg999娱乐官网 11

 

学习:C#汇总揭秘——Entity Framework 并发管理详细明白 帖子笔记 ,该帖子使用的是objectContext ,

三、悲观并发

 

上一篇:浓烈学习微框架,学习质地 下一篇:没有了