并发处理实战爱博体育app

学习:C#综合揭秘——Entity Framework
并发处理详解

帖子笔记 ,该帖子使用的是objectContext ,

学习:C#综合揭秘——Entity Framework
并发处理详解

帖子笔记 ,该帖子使用的是objectContext ,

壹 、并发相关概念

并发的品种:

第②种形式称为悲观式并发,即当3个用户已经在改动某条记下时,系统将拒绝其余用户同时修改此记录。
其次种形式称为乐观式并发,即系统允许三个用户同时修改同一条记下,系统会优先定义由数据出现所引起的产出格外处理方式,去处理修改后或许发生的冲突。常用的乐观性并发处理措施有以下两种:

    一 、保留最终修改的值。
    ② 、保留最初修改的值。
    三 、合并往往改动的值。

① 、并发相关概念

并发的项目:

首先种格局称为悲观式并发,即当二个用户已经在改动某条记下时,系统将拒绝别的用户同时修改此记录。
第三种形式称为乐观式并发,即系统允许多少个用户同时修改同一条记下,系统会预先定义由数量出现所引起的面世极度处理格局,去处理修改后或者爆发的争论。常用的乐观性并发处理方式有以下三种:

    一 、保留最终修改的值。
    ② 、保留最初修改的值。
    ③ 、合并往往改动的值。

贰 、模型属性的面世处理选项

一般来说图模型设计器中TimeStamp字段为启用并发

爱博体育app 1

<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
时,系统会对此模型属性举办检查和测试,当同3个年华对品质实行修改时,系统就会激起OptimisticConcurrencyException
至极。

 

② 、模型属性的产出处理选项

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

爱博体育app 2

<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
万分。

 

③ 、悲观并发

 

③ 、悲观并发

 

四 、乐观并发

为了消除悲观并发所带动的难点,ADO.NET Entity Framework
提供了进一步高效的无忧无虑并发处理格局。相对于LINT to SQL , ADO.NET Entity
Framework
简化了有望并发的处理情势,它能够灵活使用合并数据、保留初次输入数据、保留最新输入数据(3种办法)等措施处理并发争论。

④ 、乐观并发

为了消除悲观并发所带来的难点,ADO.NET Entity Framework
提供了一发迅猛的开朗并发处理形式。相对于LINT to SQL , ADO.NET Entity
Framework
简化了开始展览并发的处理方式,它可以灵活选择合并数据、保留初次输入数据、保留最新输入数据(3种办法)等格局处理并发冲突。

4.1 以联合方式处理并发数据

总计:当模型属性的 ConcurencyMode 为暗中同意值 None
,一旦同三个对象属性同时被修改,系统将以统一数据的点子处理并发争论,那也是
Entity Framework 处理并发争辩的默许格局。

集合处理格局如下:

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

(2)当同一时半刻间对相同对象的分裂性质作出修改,系统将保留已被改动的属性值。上面用多少个例子作出表明:

爱博体育app 3

运营结果:

爱博体育app 4

#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} \r\n ",
                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不可能:

爱博体育app 5

使用Entry也报错

爱博体育app 6

最终参考如下帖子

爱博体育app 7

/// <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 以统一形式处理并发数据

总括:当模型属性的 ConcurencyMode 为默许值 None
,一旦同1个目的属性同时被涂改,系统将以统一数据的章程处理并发抵触,那也是
Entity Framework 处理并发抵触的暗许形式。

统一处理格局如下:

(1)当同近年来间针对同一个对象属性作出修改,系统将保留最新输入的属性值。

(2)当同一时半刻间对同一对象的不比属性作出修改,系统将保存已被修改的属性值。下边用三个例证作出表达:

爱博体育app 8

运营结果:

爱博体育app 9

#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} \r\n ",
                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不得以:

爱博体育app 10

使用Entry也报错

爱博体育app 11

末段参考如下帖子

爱博体育app 12

/// <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
能以健全的建制灵活处理同时更新同一对象的操作,但要是删除操作与立异操作同时运维时,就大概存在逻辑性的可怜。

例如:三个客户端同时加载了同3个指标,第③个客户端更新了数额后,把数据重复提交。但在付给前,第一个客户端已经把数据库中的已有数量删除。

那时候,上下文中的靶子处于区别的动静下,将会抓住
OptimisticConcurrencyException 十分(ObjectContext
与DBContext三种办法下,极度不平等,具体要遵照测试结果本人看清)。
相见此13分时,可以用 try(OptimisticConcurrencyException){…} catch
{…} 格局抽薪止沸相当,然后改变对象的State 属性。把EntityState 更改为 Added
,被删去的数目便会被再次加载。若把 EntityState 更改为 Detached
时,数据便会被顺顺当当删除。上面把指标的 EntityState 属性更改为 Added
作为例子。

爱博体育app 13

代码如下:处理结果前后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;
        }

并发时的不行类型:

爱博体育app 14

ID爆发了扭转

爱博体育app 15

 

4.1 剔除与立异操作同时运转(非框架自动处理能力,开发自动修改情状手动增添的)**

Entity Framework
能以完善的编制灵活处理同时立异同一对象的操作,但倘诺删除操作与更新操作同时运行时,就只怕存在逻辑性的那么些。

譬如说:三个客户端同时加载了同1个目的,第③个客户端更新了数据后,把数量再一次提交。但在付给前,第贰个客户端已经把数据库中的已有数据删除。

那时,上下文中的对象处于不相同的情况下,将会抓住
OptimisticConcurrencyException 卓殊(ObjectContext
与DBContext三种艺术下,非凡差别,具体要按照测试结果自个儿判断)。
境遇此丰硕时,能够用 try(OptimisticConcurrencyException){…} catch
{…} 格局消灭净尽相当,然后改成对象的State 属性。把EntityState 更改为 Added
,被删除的多少便会被重新加载。若把 EntityState 更改为 Detached
时,数据便会被顺顺当当删除。下边把对象的 EntityState 属性更改为 Added
作为例子。

爱博体育app 16

代码如下:处理结果前后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;
        }

并发时的丰富类型:

爱博体育app 17

ID爆发了变动

爱博体育app 18

 

4.3 当产生多少出现时,保留最后(最新:末了一回)输入的多寡

要证实输入对象的属性,必须先把该属性的 ConcurencyMode 设置为
Fixed,那样系统就会实时检查和测试对象属性的输入值 。
当该属性被同时创新,系统便会激起 OptimisticConcurrencyException
非常。捕获该特别后,能够动用 ObjectContext.Refresh (RefreshMode,object)
刷新上下文中该指标的气象,当 RefreshMode 为 ClientWins
时,系统将会保持内外文中的后日有多少,即保留最新输入的指标值。此时再选用ObjectContext.SaveChanges,
系统就会把最新输入的对象值插手数据库个中。

在上面包车型大巴事例当,系统运转前先把 Person 的 FirstName、SecondName
八个属性的 ConcurencyMode
属性设置为Fixed,使系统能监视那多少个性格的更改。所输入的数据只在FirstName、SecondName
两个值中作出修改。在数据交到前先以 DisplayProperty
方法呈现数据库最初的数目属性,在数码初次更新后再一次调用 DisplayProperty
突显更新后的数额属性。在其次次创新数据时,由调用ObjectContext.SaveChanges时,数据库中的数据现已被修改,与方今上下文ObjectContext
的多寡存在冲突,系统将激励OptimisticConcurrencyException
格外,此时把吸引这多少个的靶子属性再度体现出来。对相当举办拍卖后,显示数据库中最终的指标值。

 

 

考察测试结果,可知当RefreshMode状态为ClientWins时,系统将会保留上下文其中的靶子属性,使用此方法能够在产生并发至极时保持最新输入的目的属性。

 

4.3 当产生多少现身时,保留最终(最新:最终三回)输入的数目

要证实输入对象的品质,必须先把该属性的 ConcurencyMode 设置为
Fixed,这样系统就会实时检查和测试对象属性的输入值 。
当该属性被同时创新,系统便会激起 OptimisticConcurrencyException
分外。捕获该特别后,能够利用 ObjectContext.Refresh (RefreshMode,object)
刷新上下文中该目的的意况,当 RefreshMode 为 ClientWins
时,系统将会保持内外文中的前日有数据,即保留最新输入的对象值。此时再使用ObjectContext.SaveChanges,
系统就会把最新输入的指标值参加数据库个中。

在上边包车型地铁例证当,系统运行前先把 Person 的 FirstName、SecondName
四个天性的 ConcurencyMode
属性设置为Fixed,使系统能监视那多个属性的变动。所输入的数码只在FirstName、SecondName
四个值中作出修改。在数码提交前先以 DisplayProperty
方法显示数据库最初的多少属性,在多少初次更新后再行调用 DisplayProperty
显示更新后的数据属性。在其次次革新数据时,由调用ObjectContext.SaveChanges时,数据库中的数据已经被改动,与日前上下文ObjectContext
的数目存在争论,系统将激励OptimisticConcurrencyException
卓殊,此时把吸引那些的对象属性再次展示出来。对格外举行拍卖后,展现数据库中最终的指标值。

 

 

考察测试结果,可见当RefreshMode状态为ClientWins时,系统将会保留上下文个中的对象属性,使用此方法能够在产生并发十分时保持最新输入的指标属性。

 

4.4 当发生多少现身时,保留最早(最初:最早三回)输入的多少

把对象属性的 ConcurencyMode 设置为 Fixed 后,同时创新该属性,将会刺激
OptimisticConcurrencyException 相当。此时选拔 ObjectContext.Refresh
(RefreshMode,object) 刷新上下文中该指标的气象,当 RefreshMode 为
StoreWins 时,系统就会把数据源中的数据代表上下文中的多寡。
因为初次调用 SaveChanges,数据足以成功保存到数据库。可是在 ObjectContext
并未释放时,再度使用 SaveChanges
异步更新数据,就会掀起OptimisticConcurrencyException 并发很是。当
RefreshMode 为 StoreWins 时,系统就会保留初次输入的数量属性。
此例子与地点的例子13分相似,只是把 RefreshMode 改为 StoreWins
而已。在作业逻辑较为复杂的的系统在这之中,提议采纳此格局处理并发卓殊。在保留最初输入的数码修改属性后,把属性返还给客户,让客户实行相比后再决定下一步的处理格局。

爱博体育app 19

爱博体育app 20

 

考察测试结果,可知当 RefreshMode 状态为 StoreWins
时,系统将会以数据源中的数据代表上下文个中的指标属性。在工作逻辑较为复杂的的种类当中,提议利用此办法处理并发格外。


链接: https://pan.baidu.com/s/1gfu6fZl 密码: fyb3

演练的源码,有改正的失实的心上人记得分享

4.4 当发生多少出现时,保留最早(最初:最早1回)输入的多寡

把指标属性的 ConcurencyMode 设置为 Fixed 后,同时更新该属性,将会刺激
OptimisticConcurrencyException 相当。此时利用 ObjectContext.Refresh
(RefreshMode,object) 刷新上下文中该对象的景观,当 RefreshMode 为
StoreWins 时,系统就会把数据源中的数据代表上下文中的数量。
因为初次调用 SaveChanges,数据足以成功保存到数据库。可是在 ObjectContext
并未释放时,再一次利用 SaveChanges
异步更新数据,就会抓住OptimisticConcurrencyException 并发相当。当
RefreshMode 为 StoreWins 时,系统就会保留初次输入的数目属性。
此例子与地点的事例拾壹分相似,只是把 RefreshMode 改为 StoreWins
而已。在作业逻辑较为复杂的的种类个中,建议选用此措施处理并发极度。在保留最初输入的数额修改属性后,把属性返还给客户,让客户开始展览对照后再决定下一步的处理格局。

爱博体育app 21

爱博体育app 22

 

观测测试结果,可知当 RefreshMode 状态为 StoreWins
时,系统将会以数据源中的数据代表上下文个中的靶子属性。在工作逻辑较为复杂的的系统当中,提出利用此办法处理并发相当。


链接: https://pan.baidu.com/s/1gfu6fZl 密码: fyb3

演习的源码,有修正的荒唐的情侣记得分享

相关文章