EF架(jia)構~EF異(yi)步(bu)(bu)改造之路~讓DbContextRepository去實現異(yi)步(bu)(bu)接口(kou)
上一講中,我們(men)(men)定義了三個(ge)異步操作接(jie)口,這(zhe)(zhe)回我們(men)(men)將對它進(jin)行(xing)實現(xian)(xian)(xian),而(er)有(you)一(yi)個(ge)基礎知識(shi)需要大(da)家清楚,那就是實現(xian)(xian)(xian)接(jie)口的(de)(de)(de)方(fang)(fang)式(shi)(shi)(shi),一(yi)般我們(men)(men)使用默認的(de)(de)(de)方(fang)(fang)式(shi)(shi)(shi)(隱式(shi)(shi)(shi)實現(xian)(xian)(xian)),這(zhe)(zhe)種方(fang)(fang)法實現(xian)(xian)(xian)的(de)(de)(de)接(jie)口方(fang)(fang)式(shi)(shi)(shi)均為public,即它可以脫離(li)接(jie)口,而(er)直接(jie)通過(guo)類(lei)對象去訪問,而(er)當一(yi)個(ge)類(lei)繼承多(duo)個(ge)接(jie)口,而(er)這(zhe)(zhe)些(xie)接(jie)口中都(dou)有(you)相同的(de)(de)(de)方(fang)(fang)法時(shi),我們(men)(men)就需要顯示實現(xian)(xian)(xian)接(jie)口了,顯示實現(xian)(xian)(xian)的(de)(de)(de)接(jie)口成員只(zhi)能(neng)通過(guo)接(jie)口實例(li)去訪問它,今(jin)天我們(men)(men)對DbContextRepository的(de)(de)(de)改造就用到了這(zhe)(zhe)個(ge)特性(xing)。
基本關鍵字
async:用來標識這個(ge)方(fang)(fang)法(fa)(fa)為(wei)異步方(fang)(fang)法(fa)(fa)
await:用(yong)在異(yi)(yi)步方(fang)法(fa)(fa)中,它可以等(deng)待異(yi)(yi)步方(fang)法(fa)(fa)的返回(hui)值,即用(yong)來阻塞主線(xian)程,迫使它等(deng)待異(yi)(yi)步請(qing)求,當請(qing)求成功返回(hui)后,再執行下面的代碼(ma)
Task:異步返回的結果,它有泛型(xing)版本,Task表(biao)示返回為(wei)void,而(er)使(shi)用泛型(xing)版本時Task<T>返回結果為(wei)類型(xing)T
EF6引入的異(yi)步提交機制
public virtual Task<int> SaveChangesAsync();
一般(ban)地,倉(cang)儲大叔(shu)習慣將系(xi)統方(fang)法(fa)變為自(zi)已的(de)(de)方(fang)法(fa),這(zhe)樣(yang)方(fang)便(bian)以后(hou)去維(wei)護,如(ru)向(xiang)SaveChangesAsync方(fang)法(fa)添加(jia)個什么日(ri)志,事(shi)件之類的(de)(de)東西,所(suo)以,就有了自(zi)己的(de)(de)版本。
/// <summary> /// 異步提交到數據庫 /// </summary> protected async Task SaveChangesAsync() { try { await Db.SaveChangesAsync(); } catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)//捕(bu)獲實體(ti)驗(yan)證(zheng)異(yi)常 { 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() + "處(chu)理時(shi)間:" + DateTime.Now); } catch (OptimisticConcurrencyException)//并發沖(chong)突(tu)異常(chang) { } catch (Exception ex)//捕獲所有(you)異常 { if (Logger == null)//如果沒有定義日志(zhi)功能,就把異常拋出(chu)來吧 throw new Exception(ex.Message); Logger(ex.Message + "處理時間:" + DateTime.Now); }
對DbContextRepository進行改造
下面代碼,選自倉(cang)儲大叔的(de)(de)DbContextRepository.cs文件,它是顯式實現的(de)(de)異步操作接(jie)口(kou)的(de)(de),具(ju)體實現如下
#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)//并(bing)發沖突(tu)異(yi)常(chang) { } } 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
好(hao)了,到目前為(wei)止我們對(dui)DbContextRepository的(de)(de)改(gai)造就結束了,下一講我們將(jiang)介紹如何在具體(ti)項目中(zhong)使用EF的(de)(de)異(yi)步功能(neng),敬請(qing)期(qi)待!