HTML5技术

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

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

ConcurrencyCheck(DbQueryCommit readerWriter1, DbQueryCommit readerWriter2){ int id = 1 ;Blog blog1 = readerWriter1.QueryBlog (id);Blog blog2 = readerWriter2.QueryBlog (id);readerWriter1.Commit(() = {

ConcurrencyCheck(DbQueryCommit readerWriter1, DbQueryCommit readerWriter2) { int id = 1; Blog blog1 = readerWriter1.Query<Blog>(id); Blog blog2 = readerWriter2.Query<Blog>(id); readerWriter1.Commit(() => { blog1.Name = nameof(readerWriter1); blog1.Count = 2; }); readerWriter2.Commit(() => { blog2.Name = nameof(readerWriter2); blog2.Count = 2; }); }

此时再来调用该方法:

var efContext1 = new EFCoreContext(); var d1 = new DbQueryCommit(efContext1); var efContext2 = new EFCoreContext(); var d2 = new DbQueryCommit(efContext2); //var efContext3 = new EFCoreContext(); //var d3 = new DbQueryCommit(efContext3); Concurrency.ConcurrencyCheck(d1, d2);

当我们利用两个上下文1和2去读取数据时此时Name = 'Jeffcky',当上下文1更新时在快照中根据主键和Name去查找数据库,查找到Name后并令Name = 'readerWriter1'成功更新,但是上下2去更新Name = 'readerWriter2'时,此时在快照中根据主键和Name去查找数据库,发现不存在该条数据,同时我们设置了并发Token,最终导致出现 DbUpdateConcurrencyException 并发更新异常。解决并发个两点一个是上述设置并发Token,另外一个则是设置行版本,下面我们也来看下,首先我们在类中增加一个行版本的字节属性。

public byte[] RowVersion { get; set; }

同时对该行版本进行映射标识。

pc.Property(p => p.RowVersion).IsRequired().IsRowVersion().ValueGeneratedOnAddOrUpdate();

为了很好演示行版本并发,我们增加一个属性来打印行版本字符串。

public string RowVersionString => $X16;

同样我们定义一个调用行版本的方法:

RowVersion(DbQueryCommit readerWriter1, DbQueryCommit readerWriter2) { int id = 1; Blog blog1 = readerWriter1.Query<Blog>(id); Console.WriteLine(blog1.RowVersionString); Blog blog2 = readerWriter2.Query<Blog>(id); Console.WriteLine(blog2.RowVersionString); readerWriter1.Commit(() => blog1.Name = nameof(readerWriter1)); Console.WriteLine(blog1.RowVersionString); readerWriter2.Commit(() => readerWriter2.Set<Blog>().Remove(blog2)); }

接下来我们调用演示看看。

var efContext1 = new EFCoreContext(); var d1 = new DbQueryCommit(efContext1); var efContext2 = new EFCoreContext(); var d2 = new DbQueryCommit(efContext2); //var efContext3 = new EFCoreContext(); //var d3 = new DbQueryCommit(efContext3); Concurrency.RowVersion(d1, d2);

我们从上可以明显看出当查出数据库中的行版本值为 0x000000000073 ,接着readerWriter1更新后其行版本增加为 0x000000000074 ,当我们利用readerWriter2去删除查询出id = 1的数据时,此时会根据当前主键和行版本为 0x000000000073 去查找数据库,但是此时没有找到数据,导致同样如上述并发Token一样出现并发异常。

EntityFramework Core并发中级版解析

并发异常我们可以通过 DbUpdateConcurrencyException  来获取,该类继承自 DbUpdateException ,该类中的参数 EntityEntry 为一个集合,利用它则可以获取到对应的数据库中的值以及当前更新值等,所以我们可以自定义并发异常解析,如下:

public class DbUpdateException : Exception { public virtual IReadOnlyList<EntityEntry> Entries { get; } } public class DbUpdateConcurrencyException : DbUpdateException { //TODO }

这里我们需要弄明白存在EntityEntry中的值类型,比如DbUpdateConcurrencyException的参数为exception。我们通过如下则可以获取到被跟踪的实体状态。

var tracking = exception.Entries.Single();

此时存在数据库中的原始值则为如下:

var original = tracking.OriginalValues.ToObject();

而当前需要更新的值则为如下:

var current = tracking.CurrentValues.ToObject();

而数据库中的值则为已经提交更新的值:

;

 

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

网友点评
i