EF异步改造之路~第二回 让DbContextRepository去实现异步接口

上一讲中,我们定义了三个异步操作接口,这回我们将对它进行实现,而有一个基础知识需要大家清楚,那就是实现接口的方式,一般我们使用默认的方式(隐式实现),这种方法实现的接口方式均为public,即它可以脱离接口,而直接通过类对象去访问,而当一个类继承多个接口,而这些接口中都有相同的方法时,我们就需要显示实现接口了,显示实现的接口成员只能通过接口实例去访问它,今天我们对DbContextRepository的改造就用到了这个特性。

基本关键字

async:用来标识这个方法为异步方法

await:用在异步方法中,它可以等待异步方法的返回值,即用来阻塞主线程,迫使它等待异步请求,当请求成功返回后,再执行下面的代码

Task:异步返回的结果,它有泛型版本,Task表示返回为void,而使用泛型版本时Task<T>返回结果为类型T

EF6引入的异步提交机制

 public virtual Task<int> SaveChangesAsync();

一般地,仓储大叔习惯将系统方法变为自已的方法,这样方便以后去维护,如向SaveChangesAsync方法添加个什么日志,事件之类的东西,所以,就有了自己的版本。

/// <summary>
        /// 异步提交到数据库
        /// </summary>
        protected async Task SaveChangesAsync()
        {
            try
            {
                await Db.SaveChangesAsync();
            }
            catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)//捕获实体验证异常
            {
                var sb = new StringBuilder();
                dbEx.EntityValidationErrors.First().ValidationErrors.ToList().ForEach(i =>
                {
                    sb.AppendFormat("属性为:{0},信息为:{1}\n\r", i.PropertyName, i.ErrorMessage);
                });
                if (Logger == null)
                    throw new Exception(sb.ToString());
                Logger(sb.ToString() + "处理时间:" + DateTime.Now);

            }
            catch (OptimisticConcurrencyException)//并发冲突异常
            {

            }
            catch (Exception ex)//捕获所有异常
            {
                if (Logger == null)//如果没有定义日志功能,就把异常抛出来吧
                    throw new Exception(ex.Message);
                Logger(ex.Message + "处理时间:" + DateTime.Now);
            }

对DbContextRepository进行改造

下面代码,选自仓储大叔的DbContextRepository.cs文件,它是显式实现的异步操作接口的,具体实现如下

#region 异步操作-显示实现的接口,只能为接口实例进行调用
        #region IExtensionRepositoryAsync<TEntity> 成员

        async System.Threading.Tasks.Task IExtensionRepositoryAsync<TEntity>.Insert(IEnumerable<TEntity> item)
        {
            item.ToList().ForEach(i =>
            {
                Db.Entry<TEntity>(i);
                Db.Set<TEntity>().Add(i);
            });
            await this.SaveChangesAsync();
        }

        async System.Threading.Tasks.Task IExtensionRepositoryAsync<TEntity>.Update(IEnumerable<TEntity> item)
        {
            item.ToList().ForEach(i =>
            {
                Db.Set<TEntity>().Attach(i);
                Db.Entry(i).State = EntityState.Modified;
            });
            try
            {
                await this.SaveChangesAsync();
            }
            catch (OptimisticConcurrencyException)//并发冲突异常
            {
            }
        }

        async System.Threading.Tasks.Task IExtensionRepositoryAsync<TEntity>.Delete(IEnumerable<TEntity> item)
        {
            item.ToList().ForEach(i =>
            {
                Db.Set<TEntity>().Attach(i);
                Db.Set<TEntity>().Remove(i);
            });
            await this.SaveChangesAsync();
        }

        async System.Threading.Tasks.Task IExtensionRepositoryAsync<TEntity>.BulkInsert(IEnumerable<TEntity> item, bool isRemoveIdentity)
        {
            await Task.Run(() =>
            {
                this.BulkInsert(item, isRemoveIdentity);
            });
        }

        async System.Threading.Tasks.Task IExtensionRepositoryAsync<TEntity>.BulkInsert(IEnumerable<TEntity> item)
        {
            await Task.Run(() =>
            {
                this.BulkInsert(item);
            });
        }

        async System.Threading.Tasks.Task IExtensionRepositoryAsync<TEntity>.BulkUpdate(IEnumerable<TEntity> item, params string[] fieldParams)
        {
            await Task.Run(() =>
            {
                this.BulkUpdate(item);
            });
        }

        async System.Threading.Tasks.Task IExtensionRepositoryAsync<TEntity>.BulkDelete(IEnumerable<TEntity> item)
        {
            await Task.Run(() =>
            {
                this.BulkDelete(item);
            });
        }

        #endregion

        #region IRepositoryAsync<TEntity> 成员

        async System.Threading.Tasks.Task IRepositoryAsync<TEntity>.Insert(TEntity item)
        {
            OnBeforeSaved(new SavedEventArgs(item, SaveAction.Insert));
            Db.Entry<TEntity>(item);
            Db.Set<TEntity>().Add(item);
            await this.SaveChangesAsync();
            OnAfterSaved(new SavedEventArgs(item, SaveAction.Insert));
        }

        async System.Threading.Tasks.Task IRepositoryAsync<TEntity>.Delete(TEntity item)
        {
            OnBeforeSaved(new SavedEventArgs(item, SaveAction.Delete));
            Db.Set<TEntity>().Attach(item);
            Db.Set<TEntity>().Remove(item);
            await this.SaveChangesAsync();
            OnAfterSaved(new SavedEventArgs(item, SaveAction.Delete));
        }

        async System.Threading.Tasks.Task IRepositoryAsync<TEntity>.Update(TEntity item)
        {
            OnBeforeSaved(new SavedEventArgs(item, SaveAction.Update));
            Db.Set<TEntity>().Attach(item);
            Db.Entry(item).State = EntityState.Modified;
            try
            {
                await this.SaveChangesAsync();
            }
            catch (OptimisticConcurrencyException)//并发冲突异常
            {

            }

            OnAfterSaved(new SavedEventArgs(item, SaveAction.Update));
        }

        #endregion
        #endregion

好了,到目前为止我们对DbContextRepository的改造就结束了,下一讲我们将介绍如何在具体项目中使用EF的异步功能,敬请期待!

时间: 2024-10-27 13:28:18

EF异步改造之路~第二回 让DbContextRepository去实现异步接口的相关文章

EF异步改造之路~第一回 仓储接口的改造

C#5.0带来了并行编程 {C#1.0托管代码→C#2.0泛型→C#3.0LINQ→C#4.0动态语言→C#5.0异步编程} 随着C#5.0在.net4.5出来之后,它们主推的并行技术也逐渐变得越来越热,这种热量已经传到了我这里,身为仓储大叔的我,一定也对自己的仓储进行并行化的改造,这是大势所趋,呵呵,今天主要是把我的IRepository.Core项目进行扩展,即添加一些对应的并行接口,然后让我的并行(异步)仓储去实现它,事实上,.net的ef这块,实现异步(并行)非常容易,在C#5.0里由于

EF架构~EF异步改造之路~仓储接口的改造~续

回到目录 在写完仓储接口的改造改造后,总觉得有个代码的坏味道,这种味道源于它的DRP,即重复的代码太多了,即异步操作和同步操作其实只是在insert,update和delete上有所不同,获取数据的方法都是一样的,所以,我最后决定,将异步的接口进行改造,让它更加合理,方法后都加上Async的后缀,看上去也更像是个异步方法,呵. 改造后的异步接口 /// <summary> /// 异步操作 /// 基础的数据操作规范 /// 与ORM架构无关 /// </summary> ///

[林大帅作品连载]第二回 环岛路绝景配绝音 俏学妹书店忆书院

第二回 环岛路绝景配绝音 俏学妹书店忆书院    诗云:      漫言旧情心未冷,夜寂乱稿伴孤灯.            本意沈吟新人至,人生何处不相逢?       话接上回,林二抬头一看,只见那女童生微笑吟吟到:“叨劳了,我几个路过宝地,只因醉心于这路旁小花,竟忘了投宿之事,请问八日客栈位于何处?”,话未叙完,两颊便已微红.林二一见,便来了精神,方才丢手机,钱袋之事,早已抛到九霄云外.却故意顿了顿道:“几位姑娘莫急,这前面不远处便是‘八日’客栈,小可无事可领诸位前往”.       说罢那

[转] 擎天哥as3教程系列第二回——性能优化

所谓性能优化主要是让游戏loading和运行的时候不卡. 一  优化fla导出的swf的体积? 1,  在flash中,舞台上的元件最多,生成的swf越大,库里面有连接名的元件越多,swf越大.当舞台上没有元件且库里面的元件没有连接名的话生成的swf最小. 2,  一个flash动画有10帧,10帧上面全部是位图和用一个位图播放器播放这10张图片谁消耗的cpu更高? 答:flash动画播放消耗性能更高,因为swf文件里虽然也是位图,但是swf里面的播放机制是能播放位图,矢量图,声音,视频等.所以

七日Python之路--第二天

由于之前使用过一段Ubuntu,所以基本命令啥的都还可以.装差利器Vim也是使用过一段时间的. Ubuntu快速打开终端Alt+Ctrl+T,这样才显得犀利一些嘛.说实话,终端编辑文件啥的,确实比Win下面爽的多,毕竟Win主打图形化的嘛.感觉废话有点多. 今天本想继续研究枯燥的官方文档,但昨夜偶然发现网易云课堂,如此犀利的资源怎能浪费. 零基础入门学习Python 讲师:小甲鱼 发布者:鱼C工作室 ,这个视频还是个人还是比较喜欢的,之前在youku上看到过几段,但是不全.http://stud

Node.js之路【第三篇】NodeJS异步实现

NodeJS异步实现 Node.js异步编程的直接体现就是回调,它依托于回调来实现,但不能说使用了回调他就是异步了 回调函数在完成任务后就会被调用,Node使用了大量的回调函数,Node所有的API都支持回调函数 例如:我们可以一边读取文件一边执行其他命令,在文件读取完成后,我们将文件内容作为回调的参数返回,这样执行代码的时候就不会有阻塞或等待I/O操作 这样就打打提高了Node.js性能,可以处理大量的并发请求. 一.阻塞代码示例 1.创建一个测试文件text.txt文件内容如下: 文件I/O

第二十九课:javascript异步处理

大家知道javascript中有多少方法能够实现异步处理吗?setTimeout(),setInterval()是最常用的两个.XMLHttpRequest对象,进行ajax请求时.postMessage()进行跨域操作时.WebWorker创建新的线程时.setImmediate方法(新的setTimeout方法).requestAnimationFrame进行动画操作时.这些东西都有一个共同的特点,就是拥有一个回调函数.有的异步API还提供了相对应的中断API,比如:clearTimeout

python之路第二天

一 .Python引入模块 1.模块是导入别人已经写好的python文件,里面已经有一些写好的功能,可以直接拿来使用使用import 关键字导入需要的模块,导入模块时,默认会在当前目录下去寻找该文件,如果当前目录下没有的话,回去python的环境变量中找,如果找不到就报错2.sys.argv 获取传入的参数,第一个参数是文件名 sys.path 打印环境变量 os模块是和操作系统相关的命令 os.system('ls') 执行操作系统命令,返回的是一个执行结果,成功或者失败,成功返回0 os.p

python学习之路 第二天

1.import 导入模块 #!/usr/bin/python # -*- coding:utf-8 -*- import sys print(sys.argv) 2.字符串常用方法: 移除空白: strip 分割: split 长度:len(obj) 索引:obj[1] 切片:obj[1:],obj[0:9] 3.列表创建方法: a = []1,2,3,4,5] a = list(1,2,3,4,5) 4.#!/usr/bin/python # -*- coding:utf-8 -*- a =