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