索引html
簡述算法
從今天開始,咱們逐步把修正先後的源碼分享給你們,仍是百度網盤分享,百度網盤只發兩次,兩次都失效後,請你們互相傳遞。sql
數據庫,已經在上一章發佈完成的項目中給你們了,這裏再也不重複發送數據庫。數據庫
今天,分享的是修改先後的倉儲IRepository、RepositoryBase框架
若是你們仔細看過以前的倉儲IRepository、RepositoryBase,那麼你們確定會發現,這個類不管是在效率上仍是邏輯上,仍是有不少不合適、不合理的。我原本是想在 【無私分享:ASP.NET CORE 項目實戰】目錄索引 系列中逐步修改,可是通過再三考慮,若是把這個源碼直接給你們,對於剛接觸的朋友實在是太不負責任,容易產生誤導,因此,仍是要在這裏進行修正。異步
在【無私分享:ASP.NET CORE 項目實戰(第五章)】Repository倉儲 UnitofWork 這篇文章中,簡單介紹了一下我的對於UnitOfWrok的理解,雖然 EF 是自帶事務的,可是咱們的 Context.SaveChanges() 無疑拋棄了統一的事務,同時,做爲一個封裝的倉儲類,咱們是應該提供 串行和並行 兩種方式的,至於到底用不用異步方式,這個咱們不能氾濫,異步不是沒有損耗的,咱們只是提供兩種方式,到底用什麼,要根據業務須要調用,而不是一味的異步方式,全部的東西都是過無不及。ide
這是咱們以前的Service 類庫:post
咱們添加 IUnitOfWork 接口 和 UnitOfWork 實現類this
1 namespace Service 2 { 3 public interface IUnitOfWork 4 { 5 /// <summary> 6 /// 提交 7 /// </summary> 8 /// <returns></returns> 9 bool Commit(); 10 16 } 17 }
1 public class UnitOfWork : IUnitOfWork, IDisposable 2 { 3 #region 數據上下文 4 5 private DbContext context = new MyConfig().db; 6 /// <summary> 7 /// 數據上下文 8 /// </summary> 9 public DbContext _Context 10 { 11 get 12 { 13 context.Configuration.ValidateOnSaveEnabled = false; 14 return context; 15 } 16 } 17 18 #endregion 19 20 /// <summary> 21 /// 提交 22 /// </summary> 23 /// <returns></returns> 24 public bool Commit() 25 { 26 return _Context.SaveChanges() > 0; 27 } 28 29 public void Dispose() 30 { 31 if (_Context != null) 32 { 33 _Context.Dispose(); 34 } 35 GC.SuppressFinalize(this); 36 } 37 }
首先,把涉及到事務的沒用都刪掉:url
修改單模型CRUD操做:①、增長異步方式 ②、添加 bool IsCommit = true 參數,判斷是否提交
這個參數的主要做用是,咱們在進行單項操做的時候,能夠直接提交保存,當進行多項操做的時候,咱們這個傳入False,而後 經過 UnitOfWork 統一提交保存
1 #region 單模型 CRUD 操做 2 /// <summary> 3 /// 增長一條記錄 4 /// </summary> 5 /// <param name="entity">實體模型</param> 6 /// <param name="IsCommit">是否提交(默認提交)</param> 7 /// <returns></returns> 8 bool Save(T entity, bool IsCommit = true); 9 /// <summary> 10 /// 增長一條記錄(異步方式) 11 /// </summary> 12 /// <param name="entity">實體模型</param> 13 /// <param name="IsCommit">是否提交(默認提交)</param> 14 /// <returns></returns> 15 Task<bool> SaveAsync(T entity, bool IsCommit = true); 16 17 /// <summary> 18 /// 更新一條記錄 19 /// </summary> 20 /// <param name="entity">實體模型</param> 21 /// <param name="IsCommit">是否提交(默認提交)</param> 22 /// <returns></returns> 23 bool Update(T entity, bool IsCommit = true); 24 /// <summary> 25 /// 更新一條記錄(異步方式) 26 /// </summary> 27 /// <param name="entity">實體模型</param> 28 /// <param name="IsCommit">是否提交(默認提交)</param> 29 /// <returns></returns> 30 Task<bool> UpdateAsync(T entity, bool IsCommit = true); 31 32 /// <summary> 33 /// 增長或更新一條記錄 34 /// </summary> 35 /// <param name="entity">實體模型</param> 36 /// <param name="IsSave">是否增長</param> 37 /// <param name="IsCommit">是否提交(默認提交)</param> 38 /// <returns></returns> 39 bool SaveOrUpdate(T entity, bool IsSave, bool IsCommit = true); 40 /// <summary> 41 /// 增長或更新一條記錄(異步方式) 42 /// </summary> 43 /// <param name="entity">實體模型</param> 44 /// <param name="IsSave">是否增長</param> 45 /// <param name="IsCommit">是否提交(默認提交)</param> 46 /// <returns></returns> 47 Task<bool> SaveOrUpdateAsync(T entity, bool IsSave, bool IsCommit = true); 48 49 #endregion
修改多模型操做,同時增長異步方式:
1 #region 多模型操做 2 /// <summary> 3 /// 增長多條記錄,同一模型 4 /// </summary> 5 /// <param name="T1">實體模型集合</param> 6 /// <param name="IsCommit">是否提交(默認提交)</param> 7 /// <returns></returns> 8 bool SaveList(List<T> T1, bool IsCommit = true); 9 /// <summary> 10 /// 增長多條記錄,同一模型(異步方式) 11 /// </summary> 12 /// <param name="T1">實體模型集合</param> 13 /// <param name="IsCommit">是否提交(默認提交)</param> 14 /// <returns></returns> 15 Task<bool> SaveListAsync(List<T> T1, bool IsCommit = true); 16 17 /// <summary> 18 /// 增長多條記錄,獨立模型 19 /// </summary> 20 /// <param name="T1">實體模型集合</param> 21 /// <param name="IsCommit">是否提交(默認提交)</param> 22 /// <returns></returns> 23 bool SaveList<T1>(List<T1> T, bool IsCommit = true) where T1 : class; 24 /// <summary> 25 /// 增長多條記錄,獨立模型(異步方式) 26 /// </summary> 27 /// <param name="T1">實體模型集合</param> 28 /// <param name="IsCommit">是否提交(默認提交)</param> 29 /// <returns></returns> 30 Task<bool> SaveListAsync<T1>(List<T1> T, bool IsCommit = true) where T1 : class; 31 32 /// <summary> 33 /// 更新多條記錄,同一模型 34 /// </summary> 35 /// <param name="T1">實體模型集合</param> 36 /// <param name="IsCommit">是否提交(默認提交)</param> 37 /// <returns></returns> 38 bool UpdateList(List<T> T1, bool IsCommit = true); 39 /// <summary> 40 /// 更新多條記錄,同一模型(異步方式) 41 /// </summary> 42 /// <param name="T1">實體模型集合</param> 43 /// <param name="IsCommit">是否提交(默認提交)</param> 44 /// <returns></returns> 45 Task<bool> UpdateListAsync(List<T> T1, bool IsCommit = true); 46 47 /// <summary> 48 /// 更新多條記錄,獨立模型 49 /// </summary> 50 /// <param name="T1">實體模型集合</param> 51 /// <param name="IsCommit">是否提交(默認提交)</param> 52 /// <returns></returns> 53 bool UpdateList<T1>(List<T1> T, bool IsCommit = true) where T1 : class; 54 /// <summary> 55 /// 更新多條記錄,獨立模型(異步方式) 56 /// </summary> 57 /// <param name="T1">實體模型集合</param> 58 /// <param name="IsCommit">是否提交(默認提交)</param> 59 /// <returns></returns> 60 Task<bool> UpdateListAsync<T1>(List<T1> T, bool IsCommit = true) where T1 : class; 61 62 /// <summary> 63 /// 刪除多條記錄,同一模型 64 /// </summary> 65 /// <param name="T1">實體模型集合</param> 66 /// <param name="IsCommit">是否提交(默認提交)</param> 67 /// <returns></returns> 68 bool DeleteList(List<T> T1, bool IsCommit = true); 69 /// <summary> 70 /// 刪除多條記錄,同一模型(異步方式) 71 /// </summary> 72 /// <param name="T1">實體模型集合</param> 73 /// <param name="IsCommit">是否提交(默認提交)</param> 74 /// <returns></returns> 75 Task<bool> DeleteListAsync(List<T> T1, bool IsCommit = true); 76 77 /// <summary> 78 /// 刪除多條記錄,獨立模型 79 /// </summary> 80 /// <param name="T1">實體模型集合</param> 81 /// <param name="IsCommit">是否提交(默認提交)</param> 82 /// <returns></returns> 83 bool DeleteList<T1>(List<T1> T, bool IsCommit = true) where T1 : class; 84 /// <summary> 85 /// 刪除多條記錄,獨立模型(異步方式) 86 /// </summary> 87 /// <param name="T1">實體模型集合</param> 88 /// <param name="IsCommit">是否提交(默認提交)</param> 89 /// <returns></returns> 90 Task<bool> DeleteListAsync<T1>(List<T1> T, bool IsCommit = true) where T1 : class; 91 92 /// <summary> 93 /// 經過Lamda表達式,刪除一條或多條記錄 94 /// </summary> 95 /// <param name="predicate"></param> 96 /// <param name="IsCommit"></param> 97 /// <returns></returns> 98 bool Delete(Expression<Func<T, bool>> predicate, bool IsCommit = true); 99 /// <summary> 100 /// 經過Lamda表達式,刪除一條或多條記錄(異步方式) 101 /// </summary> 102 /// <param name="predicate"></param> 103 /// <param name="IsCommit"></param> 104 /// <returns></returns> 105 Task<bool> DeleteAsync(Expression<Func<T, bool>> predicate, bool IsCommit = true); 106 107 /// <summary> 108 /// 執行SQL刪除 109 /// </summary> 110 /// <param name="sql">SQL語句</param> 111 /// <param name="para">Parameters參數</param> 112 int DeleteBySql(string sql, params DbParameter[] para); 113 /// <summary> 114 /// 執行SQL刪除(異步方式) 115 /// </summary> 116 /// <param name="sql">SQL語句</param> 117 /// <param name="para">Parameters參數</param> 118 Task<int> DeleteBySql(string sql, params DbParameter[] para); 119 #endregion
修改獲取多條數據操做,同時增長異步方式:
1 #region 獲取多條數據操做 2 3 /// <summary> 4 /// 返回IQueryable集合,延時加載數據 5 /// </summary> 6 /// <param name="predicate"></param> 7 /// <returns></returns> 8 IQueryable<T> LoadAll(Expression<Func<T, bool>> predicate); 9 /// <summary> 10 /// 返回IQueryable集合,延時加載數據(異步方式) 11 /// </summary> 12 /// <param name="predicate"></param> 13 /// <returns></returns> 14 Task<IQueryable<T>> LoadAllAsync(Expression<Func<T, bool>> predicate); 15 16 // <summary> 17 /// 返回List<T>集合,不採用延時加載 18 /// </summary> 19 /// <param name="predicate"></param> 20 /// <returns></returns> 21 List<T> LoadListAll(Expression<Func<T, bool>> predicate); 22 // <summary> 23 /// 返回List<T>集合,不採用延時加載(異步方式) 24 /// </summary> 25 /// <param name="predicate"></param> 26 /// <returns></returns> 27 Task<List<T>> LoadListAllAsync(Expression<Func<T, bool>> predicate); 28 29 /// <summary> 30 /// 獲取DbQuery的列表 31 /// </summary> 32 /// <param name="predicate"></param> 33 /// <returns></returns> 34 DbQuery<T> LoadQueryAll(Expression<Func<T, bool>> predicate); 35 /// <summary> 36 /// 獲取DbQuery的列表(異步方式) 37 /// </summary> 38 /// <param name="predicate"></param> 39 /// <returns></returns> 40 Task<DbQuery<T>> LoadQueryAllAsync(Expression<Func<T, bool>> predicate); 41 42 /// <summary> 43 /// 獲取IEnumerable列表 44 /// </summary> 45 /// <param name="sql">SQL語句</param> 46 /// <param name="para">Parameters參數</param> 47 /// <returns></returns> 48 IEnumerable<T> LoadEnumerableAll(string sql,params DbParameter[] para); 49 /// <summary> 50 /// 獲取IEnumerable列表(異步方式) 51 /// </summary> 52 /// <param name="sql">SQL語句</param> 53 /// <param name="para">Parameters參數</param> 54 /// <returns></returns> 55 Task<IEnumerable<T>> LoadEnumerableAllAsync(string sql, params DbParameter[] para); 56 57 /// <summary> 58 /// 獲取數據動態集合 59 /// </summary> 60 /// <param name="sql">SQL語句</param> 61 /// <param name="para">Parameters參數</param> 62 /// <returns></returns> 63 IEnumerable LoadEnumerable(string sql, params DbParameter[] para); 64 /// <summary> 65 /// 獲取數據動態集合(異步方式) 66 /// </summary> 67 /// <param name="sql">SQL語句</param> 68 /// <param name="para">Parameters參數</param> 69 /// <returns></returns> 70 Task<IEnumerable> LoadEnumerableAsync(string sql, params DbParameter[] para); 71 72 /// <summary> 73 /// 採用SQL進行數據的查詢,返回IList集合 74 /// </summary> 75 /// <param name="sql">SQL語句</param> 76 /// <param name="para">Parameters參數</param> 77 /// <returns></returns> 78 List<T> SelectBySql(string sql, params DbParameter[] para); 79 /// <summary> 80 /// 採用SQL進行數據的查詢,返回IList集合(異步方式) 81 /// </summary> 82 /// <param name="sql">SQL語句</param> 83 /// <param name="para">Parameters參數</param> 84 /// <returns></returns> 85 Task<List<T>> SelectBySqlAsync(string sql, params DbParameter[] para); 86 87 /// <summary> 88 /// 採用SQL進行數據的查詢,指定泛型,返回IList集合 89 /// </summary> 90 /// <typeparam name="T1"></typeparam> 91 /// <param name="sql"></param> 92 /// <param name="para"></param> 93 /// <returns></returns> 94 List<T1> SelectBySql<T1>(string sql, params DbParameter[] para); 95 /// <summary> 96 /// 採用SQL進行數據的查詢,指定泛型,返回IList集合 97 /// </summary> 98 /// <typeparam name="T1"></typeparam> 99 /// <param name="sql"></param> 100 /// <param name="para"></param> 101 /// <returns></returns> 102 Task<List<T1>> SelectBySqlAsync<T1>(string sql, params DbParameter[] para); 103 104 /// <summary> 105 /// 可指定返回結果、排序、查詢條件的通用查詢方法,返回實體對象集合 106 /// </summary> 107 /// <typeparam name="TEntity">實體對象</typeparam> 108 /// <typeparam name="TOrderBy">排序字段類型</typeparam> 109 /// <typeparam name="TResult">數據結果,與TEntity一致</typeparam> 110 /// <param name="where">過濾條件,須要用到類型轉換的須要提早處理與數據表一致的</param> 111 /// <param name="orderby">排序字段</param> 112 /// <param name="selector">返回結果(必須是模型中存在的字段)</param> 113 /// <param name="IsAsc">排序方向,true爲正序false爲倒序</param> 114 /// <returns>實體集合</returns> 115 List<TResult> QueryEntity<TEntity, TOrderBy, TResult>(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TOrderBy>> orderby, Expression<Func<TEntity, TResult>> selector, bool IsAsc) 116 where TEntity : class 117 where TResult : class; 118 /// <summary> 119 /// 可指定返回結果、排序、查詢條件的通用查詢方法,返回實體對象集合(異步方式) 120 /// </summary> 121 /// <typeparam name="TEntity">實體對象</typeparam> 122 /// <typeparam name="TOrderBy">排序字段類型</typeparam> 123 /// <typeparam name="TResult">數據結果,與TEntity一致</typeparam> 124 /// <param name="where">過濾條件,須要用到類型轉換的須要提早處理與數據表一致的</param> 125 /// <param name="orderby">排序字段</param> 126 /// <param name="selector">返回結果(必須是模型中存在的字段)</param> 127 /// <param name="IsAsc">排序方向,true爲正序false爲倒序</param> 128 /// <returns>實體集合</returns> 129 Task<List<TResult>> QueryEntityAsync<TEntity, TOrderBy, TResult>(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TOrderBy>> orderby, Expression<Func<TEntity, TResult>> selector, bool IsAsc) 130 where TEntity : class 131 where TResult : class; 132 133 /// <summary> 134 /// 可指定返回結果、排序、查詢條件的通用查詢方法,返回Object對象集合 135 /// </summary> 136 /// <typeparam name="TEntity">實體對象</typeparam> 137 /// <typeparam name="TOrderBy">排序字段類型</typeparam> 138 /// <param name="where">過濾條件,須要用到類型轉換的須要提早處理與數據表一致的</param> 139 /// <param name="orderby">排序字段</param> 140 /// <param name="selector">返回結果(必須是模型中存在的字段)</param> 141 /// <param name="IsAsc">排序方向,true爲正序false爲倒序</param> 142 /// <returns>自定義實體集合</returns> 143 List<object> QueryObject<TEntity, TOrderBy>(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TOrderBy>> orderby, Func<IQueryable<TEntity>, List<object>> selector, bool IsAsc) 144 where TEntity : class; 145 /// <summary> 146 /// 可指定返回結果、排序、查詢條件的通用查詢方法,返回Object對象集合(異步方式) 147 /// </summary> 148 /// <typeparam name="TEntity">實體對象</typeparam> 149 /// <typeparam name="TOrderBy">排序字段類型</typeparam> 150 /// <param name="where">過濾條件,須要用到類型轉換的須要提早處理與數據表一致的</param> 151 /// <param name="orderby">排序字段</param> 152 /// <param name="selector">返回結果(必須是模型中存在的字段)</param> 153 /// <param name="IsAsc">排序方向,true爲正序false爲倒序</param> 154 /// <returns>自定義實體集合</returns> 155 Task<List<object>> QueryObjectAsync<TEntity, TOrderBy>(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TOrderBy>> orderby, Func<IQueryable<TEntity>, List<object>> selector, bool IsAsc) 156 where TEntity : class; 157 158 /// <summary> 159 /// 可指定返回結果、排序、查詢條件的通用查詢方法,返回動態類對象集合 160 /// </summary> 161 /// <typeparam name="TEntity">實體對象</typeparam> 162 /// <typeparam name="TOrderBy">排序字段類型</typeparam> 163 /// <param name="where">過濾條件,須要用到類型轉換的須要提早處理與數據表一致的</param> 164 /// <param name="orderby">排序字段</param> 165 /// <param name="selector">返回結果(必須是模型中存在的字段)</param> 166 /// <param name="IsAsc">排序方向,true爲正序false爲倒序</param> 167 /// <returns>動態類</returns> 168 dynamic QueryDynamic<TEntity, TOrderBy>(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TOrderBy>> orderby, Func<IQueryable<TEntity>, List<object>> selector, bool IsAsc) 169 where TEntity : class; 170 /// <summary> 171 /// 可指定返回結果、排序、查詢條件的通用查詢方法,返回動態類對象集合(異步方式) 172 /// </summary> 173 /// <typeparam name="TEntity">實體對象</typeparam> 174 /// <typeparam name="TOrderBy">排序字段類型</typeparam> 175 /// <param name="where">過濾條件,須要用到類型轉換的須要提早處理與數據表一致的</param> 176 /// <param name="orderby">排序字段</param> 177 /// <param name="selector">返回結果(必須是模型中存在的字段)</param> 178 /// <param name="IsAsc">排序方向,true爲正序false爲倒序</param> 179 /// <returns>動態類</returns> 180 Task<dynamic> QueryDynamicAsync<TEntity, TOrderBy>(Expression<Func<TEntity, bool>> where, Expression<Func<TEntity, TOrderBy>> orderby, Func<IQueryable<TEntity>, List<object>> selector, bool IsAsc) 181 where TEntity : class; 182 183 #endregion
修改驗證是否存在,同時增長異步方式:
1 #region 驗證是否存在 2 3 /// <summary> 4 /// 驗證當前條件是否存在相同項 5 /// </summary> 6 bool IsExist(Expression<Func<T, bool>> predicate); 7 /// <summary> 8 /// 驗證當前條件是否存在相同項(異步方式) 9 /// </summary> 10 Task<bool> IsExistAsync(Expression<Func<T, bool>> predicate); 11 12 /// <summary> 13 /// 根據SQL驗證明體對象是否存在 14 /// </summary> 15 bool IsExist(string sql, params DbParameter[] para); 16 /// <summary> 17 /// 根據SQL驗證明體對象是否存在(異步方式) 18 /// </summary> 19 Task<bool> IsExistAsync(string sql, params DbParameter[] para); 20 21 #endregion
其他,分頁查詢、ADO.NET操做、更新字段 這幾個方法,咱們暫時不作修改:
1 #region 分頁查詢 2 /// <summary> 3 /// 通用EF分頁,默認顯示20條記錄 4 /// </summary> 5 /// <typeparam name="TEntity">實體模型</typeparam> 6 /// <typeparam name="TOrderBy">排序類型</typeparam> 7 /// <param name="index">當前頁</param> 8 /// <param name="pageSize">顯示條數</param> 9 /// <param name="where">過濾條件</param> 10 /// <param name="orderby">排序字段</param> 11 /// <param name="selector">結果集合</param> 12 /// <param name="isAsc">排序方向true正序 false倒序</param> 13 /// <returns>自定義實體集合</returns> 14 PageInfo<object> Query<TEntity, TOrderBy> 15 (int index, int pageSize, 16 Expression<Func<TEntity, bool>> where, 17 Expression<Func<TEntity, TOrderBy>> orderby, 18 Func<IQueryable<TEntity>, List<object>> selector, 19 bool IsAsc) 20 where TEntity : class; 21 /// <summary> 22 /// 對IQueryable對象進行分頁邏輯處理,過濾、查詢項、排序對IQueryable操做 23 /// </summary> 24 /// <param name="t">Iqueryable</param> 25 /// <param name="index">當前頁</param> 26 /// <param name="PageSize">每頁顯示多少條</param> 27 /// <returns>當前IQueryable to List的對象</returns> 28 Common.PageInfo<T> Query(IQueryable<T> query, int index, int PageSize); 29 /// <summary> 30 /// 普通SQL查詢分頁方法 31 /// </summary> 32 /// <param name="index">當前頁</param> 33 /// <param name="pageSize">顯示行數</param> 34 /// <param name="tableName">表名/視圖</param> 35 /// <param name="field">獲取項</param> 36 /// <param name="filter">過濾條件</param> 37 /// <param name="orderby">排序字段+排序方向</param> 38 /// <param name="group">分組字段</param> 39 /// <returns>結果集</returns> 40 Common.PageInfo Query(int index, int pageSize, string tableName, string field, string filter, string orderby, string group, params DbParameter[] para); 41 /// <summary> 42 /// 簡單的Sql查詢分頁 43 /// </summary> 44 /// <param name="index"></param> 45 /// <param name="pageSize"></param> 46 /// <param name="sql"></param> 47 /// <returns></returns> 48 Common.PageInfo Query(int index, int pageSize, string sql,string orderby,params DbParameter[] para); 49 /// <summary> 50 /// 多表聯合分頁算法 51 /// </summary> 52 PageInfo Query(IQueryable query, int index, int pagesize); 53 #endregion 54 55 #region ADO.NET增刪改查方法 56 /// <summary> 57 /// 執行增刪改方法,含事務處理 58 /// </summary> 59 object ExecuteSqlCommand(string sql, params DbParameter[] para); 60 /// <summary> 61 /// 執行多條SQL,增刪改方法,含事務處理 62 /// </summary> 63 object ExecuteSqlCommand(Dictionary<string, object> sqllist); 64 /// <summary> 65 /// 執行查詢方法,返回動態類,接收使用var,遍歷時使用dynamic類型 66 /// </summary> 67 object ExecuteSqlQuery(string sql, params DbParameter[] para); 68 #endregion 69 70 #region 更新操做 71 /// <summary> 72 /// 更新字段 73 /// </summary> 74 /// <param name="table">表名</param> 75 /// <param name="dic">被解析的字段</param> 76 /// <param name="where">條件</param> 77 /// <returns></returns> 78 bool Modify(string table, Dictionary<string, object> dic, string where); 79 #endregion
修改前的RepositoryBase:連接:http://pan.baidu.com/s/1pKYRIkF 密碼:uj2u
修改後的代碼,你們先不要直接替換掉項目中的RepositoryBase,咱們的接口和實現類也須要作一些修改。咱們在下一章,修改接口和實現類,改完後,能夠直接覆蓋掉。
原創文章 轉載請尊重勞動成果 http://yuangang.cnblogs.com