HTML5技术

EntityFramework Core并发深挖详解,一纸长文,你准备好看完了吗? - Jeffcky(4)

字号+ 作者:H5之家 来源:H5之家 2017-04-05 14:03 我要评论( )

public int DatabaseWin(Action change, ActionDbUpdateConcurrencyException handleException){change(); try { return context.SaveChanges();} catch (DbUpdateConcurrencyException exception){ return 0 ;}}

public int DatabaseWin(Action change, Action<DbUpdateConcurrencyException> handleException) { change(); try { return context.SaveChanges(); } catch (DbUpdateConcurrencyException exception) { return 0; } }

接着我们在UpdateBlog方法中在上下文2中提交数据时调用上述方法并无需再进行并发解析,如下:

readerWriter2.DatabaseWin( change: () => { blog2.Name = nameof(readerWriter2); blog2.Count = 1; }, handleException: exception => { EntityEntry tracking = exception.Entries.Single(); Blog original = (Blog)tracking.OriginalValues.ToObject(); Blog current = (Blog)tracking.CurrentValues.ToObject(); Blog database = blog1; ; Console.WriteLine(original); Console.WriteLine(); ; Console.WriteLine(databaseValue); Console.WriteLine(); ; Console.WriteLine(update); Console.WriteLine(); //resolveConflict(tracking); });

此时打印和数据库中值如下:

上述就无需再多讲了,根本没有去解析异常。

EntityFramework Core并发客户端获胜

上一大节我们演示的则是客户端获胜,这里我们只需要设置异常解析的值即可解决问题,封装一个方法,如下:

ClientWins( DbQueryCommit readerWriter1, DbQueryCommit readerWriter2, DbQueryCommit readerWriter3) => UpdateBlog(readerWriter1, readerWriter2, readerWriter3, resolveConflict: tracking => { PropertyValues databaseValues = tracking.GetDatabaseValues(); tracking.OriginalValues.SetValues(databaseValues); Console.WriteLine(tracking.State); Console.WriteLine(tracking.Property(nameof(Blog.Count)).IsModified); Console.WriteLine(tracking.Property(nameof(Blog.Name)).IsModified); Console.WriteLine(tracking.Property(nameof(Blog.Id)).IsModified); });

结果就不再演示和之前演示结果等同。我们将重点放在客户端和数据库值合并的问题,请继续往下看。

EntityFramework Core并发数据库和客户端合并

当出现并发时我们对前者使其客户端获胜而后者对于前者未有的属性则进行更新,所以我们需要首先对数据库原始值克隆一份,然后将其客户端获胜,然后将原始值和客户端属性进行比较,若数据库中的属性在原始值中的属性中没有,我们则将数据库中的值不进行更新,此时将导致当前并发中的值进行更新则呈现出我们所说客户端和数据库值进行合并更新,如下首先克隆:

PropertyValues originalValues = tracking.OriginalValues.Clone(); PropertyValues databaseValues = tracking.GetDatabaseValues(); tracking.OriginalValues.SetValues(databaseValues);

比较原始值和数据库中的属性进行比较判断,不存在则不更新。

databaseValues.Properties .Where(property => !object.Equals(originalValues[property.Name], databaseValues[property.Name])) .ToList() .ForEach(property => tracking.Property(property.Name).IsModified = false);

最终我们定义如下合并方法:

MergeClientAndDatabase( DbQueryCommit readerWriter1, DbQueryCommit readerWriter2, DbQueryCommit readerWriter3) => UpdateBlog(readerWriter1, readerWriter2, readerWriter3, resolveConflict: tracking => { PropertyValues originalValues = tracking.OriginalValues.Clone(); PropertyValues databaseValues = tracking.GetDatabaseValues(); tracking.OriginalValues.SetValues(databaseValues); #if selfDefine databaseValues.PropertyNames .Where(property => !object.Equals(originalValues[property], databaseValues[property])) .ForEach(property => tracking.Property(property).IsModified = false); #else databaseValues.Properties .Where(property => !object.Equals(originalValues[property.Name], databaseValues[property.Name])) .ToList() .ForEach(property => tracking.Property(property.Name).IsModified = false); #endif Console.WriteLine(tracking.State); Console.WriteLine(tracking.Property(nameof(Blog.Count)).IsModified); Console.WriteLine(tracking.Property(nameof(Blog.Name)).IsModified); Console.WriteLine(tracking.Property(nameof(Blog.Id)).IsModified); });

此时我们再在UpdateBlog方法添加二者不同的属性,如下:

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • EntityFramework Core不得不注意的性能优化意外收获,你会用错? - Jeffcky

    EntityFramework Core不得不注意的性能优化意外收获,你会用错? - J

    2017-04-05 14:00

  • ASP.NET Core MVC 源码学习:详解 Action 的匹配 - Savorboard

    ASP.NET Core MVC 源码学习:详解 Action 的匹配 - Savorboard

    2017-03-30 18:02

  • ASP.NET Core MVC 源码学习:MVC 启动流程详解 - Savorboard

    ASP.NET Core MVC 源码学习:MVC 启动流程详解 - Savorboard

    2017-03-27 18:01

  • 一份关于组建.NET Core开源团队的倡议书 - 彭泽0902

    一份关于组建.NET Core开源团队的倡议书 - 彭泽0902

    2017-03-13 17:02

网友点评
n