EntityFramework 6 (EF6 DBcontext) 并发处理实战。EntityFramework 6 (EF6 DBcontext) 并发处理实战。

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

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

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

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

平、并作相关概念

并发的种:

先是栽模式称为悲观式并发,即当一个用户已于改动某修记下时,系统将不容其他用户同时修改是记录。
次种模式称为乐观式并发,即系统允许多只用户以修改和同条记下,系统会先定义由数量出现所引的起异常处理模式,去处理修改后也许来的闯。常用的乐观性并发处理办法来以下几种植:

    1、保留最后修改的值。
    2、保留最初修改的价。
    3、合并往往修改的价值。

相同、并作相关概念

出现的路:

率先栽模式称为悲观式并发,即当一个用户已以窜某修记下时,系统将不容其他用户同时修改是记录。
次种模式称为乐观式并发,即系统允许多个用户同时修改和同长长的记下,系统会先定义由数量出现所引的面世异常处理模式,去处理修改后也许来的闯。常用之乐观性并发处理方式来以下几种植:

    1、保留最后修改的价值。
    2、保留最初修改的值。
    3、合并往往改的价。

次、模型属性的出现处理选项

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

大红鹰葡京会 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
时,系统会指向这模型属性进行检测,当同一个时针对性进行改动时,系统就是见面激发OptimisticConcurrencyException
异常。

 

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

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

大红鹰葡京会 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)当同一时间对同一对象的差属性作出修改,系统以保存已为涂改的属性值。下面用单薄单例证作出说明:

大红鹰葡京会 3

运转结果:

大红鹰葡京会 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不可以:

大红鹰葡京会 5

使用Entry也报错

大红鹰葡京会 6

末尾参考如下帖子

大红鹰葡京会 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
,一旦跟一个对象属性同时受涂改,系统将为合数据的点子处理并发冲突,这为是
Entity Framework 处理并发冲突之默认方式。

合并处理方式如下:

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

(2)当同一时间对平对象的差属性作出修改,系统以保存已给涂改的属性值。下面用少单例作出说明:

大红鹰葡京会 8

运作结果:

大红鹰葡京会 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不可以:

大红鹰葡京会 10

使用Entry也报错

大红鹰葡京会 11

末尾参考如下帖子

大红鹰葡京会 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
能为周之机制灵活处理同时创新同一对象的操作,但若是删除操作与更新操作而运转时,就可能是逻辑性的生。

比如说:两个客户端同时加载了和一个对象,第一只客户端更新了数码后,把数量重复提交。但在交前,第二只客户端就拿数据库被的已经出多少删除。

此时,上下文中的目标处于不同之状态下,将见面吸引
OptimisticConcurrencyException 异常(ObjectContext
以及DBContext两种艺术下,异常不均等,具体而因测试结果好判断)。
遇上是充分时,可以据此 try(OptimisticConcurrencyException){…} catch
{…} 方式一网打尽异常,然后改成对象的State 属性。把EntityState 更改为 Added
,被去除的数目就是会为再加载。若将 EntityState 更改为 Detached
时,数据就会于顺利删除。下面将目标的 EntityState 属性更改为 Added
作为例子。

大红鹰葡京会 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;
        }

并发时的要命类型:

大红鹰葡京会 14

ID发生了转移

大红鹰葡京会 15

 

4.1 抹与创新操作以运转(非框架自动处理能力,开发电动修改状态手动增加的)**

Entity Framework
能盖全面之机制灵活处理同时更新同一对象的操作,但如若删除操作及更新操作以运行时,就可能存在逻辑性的杀。

诸如:两单客户端同时加载了和一个对象,第一只客户端更新了数据后,把数据再次提交。但每当付给前,第二只客户端已拿数据库被之都生数量删除。

这,上下文中的目标处于不同之状态下,将见面抓住
OptimisticConcurrencyException 异常(ObjectContext
与DBContext两种艺术下,异常不一致,具体要根据测试结果自己看清)。
相遇是特别时,可以为此 try(OptimisticConcurrencyException){…} catch
{…} 方式一网打尽异常,然后改成对象的State 属性。把EntityState 更改为 Added
,被删除的数据就会被另行加载。若将 EntityState 更改为 Detached
时,数据就是会让顺顺当当删除。下面将对象的 EntityState 属性更改为 Added
作为例子。

大红鹰葡京会 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;
        }

连发时的老类型:

大红鹰葡京会 17

ID发生了扭转

大红鹰葡京会 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 时,系统便会保留初次输入的数额性。
以此例子与方的例证十分相似,只是把 RefreshMode 改吧 StoreWins
而已。在事情逻辑较为复杂的底系统中,建议采用这道处理并发异常。在保留最初输入的数量修改属性后,把属性返还叫客户,让客户进行自查自纠后又决定下一样步之处理方式。

大红鹰葡京会 19

大红鹰葡京会 20

 

着眼测试结果,可见当 RefreshMode 状态吧 StoreWins
时,系统以会坐数据源中之数码代表上下文当中的对象属性。在作业逻辑较为复杂的底体系当中,建议采取这个措施处理并发异常。


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

演习的源码,有正之荒谬大红鹰葡京会的心上人记得分享

4.4 当发生多少出现时,保留最早(最初:最早同破)输入的数

把对象属性的 ConcurencyMode 设置也 Fixed 后,同时更新该属性,将会晤刺激
OptimisticConcurrencyException 异常。此时利用 ObjectContext.Refresh
(RefreshMode,object) 刷新上下文中该对象的状态,当 RefreshMode 为
StoreWins 时,系统就是见面把数据源中之多少代表上下文中的多寡。
盖正调用 SaveChanges,数据好成功保存至数据库。但是以 ObjectContext
并未释放时,再次行使 SaveChanges
异步更新数据,就会见掀起OptimisticConcurrencyException 并发异常。当
RefreshMode 为 StoreWins 时,系统就是见面保留初次输入的数性。
夫例子与方的事例十分相似,只是将 RefreshMode 改也 StoreWins
而已。在工作逻辑较为复杂的的系当中,建议使用此方式处理并发异常。在保存最初输入的多少修改属性后,把属性返还受客户,让客户进行自查自纠后再行决定下一致步之处理方式。

大红鹰葡京会 21

大红鹰葡京会 22

 

观测试结果,可见当 RefreshMode 状态吧 StoreWins
时,系统以会坐数据源中之数据代表上下文当中的对象属性。在作业逻辑较为复杂的底网当中,建议用这个措施处理并发异常。


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

演习的源码,有正之荒谬的心上人记得分享

相关文章

admin

网站地图xml地图