文章出處

回到目錄

返回異步與并行目錄

上一講中,我們定義了三個異步操作接口,這回我們將對它進行實現,而有一個基礎知識需要大家清楚,那就是實現接口的方式,一般我們使用默認的方式(隱式實現),這種方法實現的接口方式均為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的異步功能,敬請期待!

回到目錄 

返回異步與并行目錄


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()