你們好,我是Rectorgit
又是星期五,很興奮,很高興,很high...啦啦啦。。。
Rector在碼友網又和你們見面啦!!!上一篇《一步一步建立ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](五)》,咱們完成了:github
經過前面幾篇文章的學習,本系列【一步一步建立ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar]】中主要涉及到的技術和組件已基本介紹到位了。接下來的系列文章主要會以知識技術整合,提高,重構等爲中心來展開,經過解決項目實戰遇到的各類問題來幫助你們有目,有方向性地學習,以達到提高你們的ASP.NENT MVC 5開發技能的效果。web
今天要給你們分享的是本系列[一步一步建立ASP.NET MVC5程序]的 進階知識:sql
說到爲何使用泛型倉儲,咱們不得不回到咱們的項目,以項目設計來驅動,說明爲何是泛型倉儲,用泛型倉儲有哪些好處。數據庫
在v1.5版本中,咱們已經實現了倉儲層和服務層。其中,倉儲層是咱們直接訪問數據庫的層,能夠經過倉儲層對數據庫進行任何有權限的操做,包括增,刪,改,查。咱們的PostRepository博文倉儲實現類已經實現了其接口中的增,刪,改,查操做,IPostRepository接口:mvc
using System.Collections.Generic; using TsBlog.Domain.Entities; namespace TsBlog.Repositories { public interface IPostRepository { /// <summary> /// 根據ID查詢單條數據 /// </summary> /// <param name="id">ID</param> /// <returns></returns> Post FindById(int id); /// <summary> /// 查詢全部數據(無分頁,大數量時請慎用) /// </summary> /// <returns></returns> IEnumerable<Post> FindAll(); /// <summary> /// 寫入實體數據 /// </summary> /// <param name="entity">博文實體類</param> /// <returns></returns> int Insert(Post entity); /// <summary> /// 更新實體數據 /// </summary> /// <param name="entity">博文實體類</param> /// <returns></returns> bool Update(Post entity); /// <summary> /// 根據實體刪除一條數據 /// </summary> /// <param name="entity">博文實體類</param> /// <returns></returns> bool Delete(Post entity); /// <summary> /// 刪除指定ID的數據 /// </summary> /// <param name="id">主鍵ID</param> /// <returns></returns> bool DeleteById(object id); /// <summary> /// 刪除指定ID集合的數據(批量刪除) /// </summary> /// <param name="ids">主鍵ID集合</param> /// <returns></returns> bool DeleteByIds(object[] ids); } }
看着這個接口類文件如今想一下,若是咱們再在數據庫新增一個用戶表(User),而後在領域項目【TsBlog.Domain】中對應建立領域實體(User),那麼按照本系列之前添加倉儲和服務層接口的步驟,咱們是否是還須要在倉儲中建立一個IUserRepository.cs,若是IUserRepository也包括了增,刪,改,查方法,那麼咱們是否是須要把IPostRepository中的全部接口方法複製到IUserRepository.cs文件中呢?同時,其實現也要一樣的複製。app
若是咱們又添加在數據庫新增了多張表,對應的倉儲接口和實現是否是又要重複以上的操做呢?ctrl+c , ctrl+v !!! 若是是這樣,還不如使用代碼生成器來得快。ide
看到這裏,但願有開發經驗的開發者們不要笑話。回想一下當初筆者在初入.NET開發的時候也是這麼幹的,複製,粘貼,代碼生成器都用過。隨着時間和經驗的積累,你也會變得更好,前提是少用或者不用複製,粘貼來實現編碼功能,即便是網上找的實現方法,也要本身動手敲一遍。函數
以上兩段話跑題了,咱們仍是切回正題,上面提到的問題實際上是有辦法來避免重複工做,減輕咱們的工做量的,即使用泛型倉儲。post
首先,打開項目【TsBlog.Repositories】,建立接口文件 IRepository.cs,在其中編寫通用的查詢接口方法:
using System; using System.Collections.Generic; using System.Linq.Expressions; namespace TsBlog.Repositories { /// <summary> /// 倉儲通用接口類 /// </summary> /// <typeparam name="T">泛型實體類</typeparam> public interface IRepository<T> where T : class, new() { /// <summary> /// 根據主值查詢單條數據 /// </summary> /// <param name="pkValue">主鍵值</param> /// <returns>泛型實體</returns> T FindById(object pkValue); /// <summary> /// 查詢全部數據(無分頁,請慎用) /// </summary> /// <returns></returns> IEnumerable<T> FindAll(); /// <summary> /// 根據條件查詢數據 /// </summary> /// <param name="predicate">條件表達式樹</param> /// <param name="orderBy">排序</param> /// <returns>泛型實體集合</returns> IEnumerable<T> FindListByClause(Expression<Func<T, bool>> predicate, string orderBy); /// <summary> /// 根據條件查詢數據 /// </summary> /// <param name="predicate">條件表達式樹</param> /// <returns></returns> T FindByClause(Expression<Func<T, bool>> predicate); /// <summary> /// 寫入實體數據 /// </summary> /// <param name="entity">實體類</param> /// <returns></returns> long Insert(T entity); /// <summary> /// 更新實體數據 /// </summary> /// <param name="entity"></param> /// <returns></returns> bool Update(T entity); /// <summary> /// 刪除數據 /// </summary> /// <param name="entity">實體類</param> /// <returns></returns> bool Delete(T entity); /// <summary> /// 刪除數據 /// </summary> /// <param name="where">過濾條件</param> /// <returns></returns> bool Delete(Expression<Func<T, bool>> @where); /// <summary> /// 刪除指定ID的數據 /// </summary> /// <param name="id"></param> /// <returns></returns> bool DeleteById(object id); /// <summary> /// 刪除指定ID集合的數據(批量刪除) /// </summary> /// <param name="ids"></param> /// <returns></returns> bool DeleteByIds(object[] ids); } }
建立泛型基類 GenericRepository.cs :
using System; using System.Collections.Generic; using System.Linq.Expressions; namespace TsBlog.Repositories { public abstract class GenericRepository<T> : IRepository<T> where T : class, new() { #region Implementation of IRepository<T> /// <summary> /// 根據主值查詢單條數據 /// </summary> /// <param name="pkValue">主鍵值</param> /// <returns>泛型實體</returns> public T FindById(object pkValue) { using (var db = DbFactory.GetSqlSugarClient()) { var entity = db.Queryable<T>().InSingle(pkValue); return entity; } } /// <summary> /// 查詢全部數據(無分頁,請慎用) /// </summary> /// <returns></returns> public IEnumerable<T> FindAll() { using (var db = DbFactory.GetSqlSugarClient()) { var list = db.Queryable<T>().ToList(); return list; } } /// <summary> /// 根據條件查詢數據 /// </summary> /// <param name="predicate">條件表達式樹</param> /// <param name="orderBy">排序</param> /// <returns>泛型實體集合</returns> public IEnumerable<T> FindListByClause(Expression<Func<T, bool>> predicate, string orderBy) { using (var db = DbFactory.GetSqlSugarClient()) { var entities = db.Queryable<T>().Where(predicate).ToList(); return entities; } } /// <summary> /// 根據條件查詢數據 /// </summary> /// <param name="predicate">條件表達式樹</param> /// <returns></returns> public T FindByClause(Expression<Func<T, bool>> predicate) { using (var db = DbFactory.GetSqlSugarClient()) { var entity = db.Queryable<T>().First(predicate); return entity; } } /// <summary> /// 寫入實體數據 /// </summary> /// <param name="entity">實體類</param> /// <returns></returns> public long Insert(T entity) { using (var db = DbFactory.GetSqlSugarClient()) { //返回插入數據的標識字段值 var i = db.Insertable(entity).ExecuteReturnBigIdentity(); return i; } } /// <summary> /// 更新實體數據 /// </summary> /// <param name="entity"></param> /// <returns></returns> public bool Update(T entity) { using (var db = DbFactory.GetSqlSugarClient()) { //這種方式會以主鍵爲條件 var i = db.Updateable(entity).ExecuteCommand(); return i > 0; } } /// <summary> /// 刪除數據 /// </summary> /// <param name="entity">實體類</param> /// <returns></returns> public bool Delete(T entity) { using (var db = DbFactory.GetSqlSugarClient()) { var i = db.Deleteable(entity).ExecuteCommand(); return i > 0; } } /// <summary> /// 刪除數據 /// </summary> /// <param name="where">過濾條件</param> /// <returns></returns> public bool Delete(Expression<Func<T, bool>> @where) { using (var db = DbFactory.GetSqlSugarClient()) { var i = db.Deleteable<T>(@where).ExecuteCommand(); return i > 0; } } /// <summary> /// 刪除指定ID的數據 /// </summary> /// <param name="id"></param> /// <returns></returns> public bool DeleteById(object id) { using (var db = DbFactory.GetSqlSugarClient()) { var i = db.Deleteable<T>(id).ExecuteCommand(); return i > 0; } } /// <summary> /// 刪除指定ID集合的數據(批量刪除) /// </summary> /// <param name="ids"></param> /// <returns></returns> public bool DeleteByIds(object[] ids) { using (var db = DbFactory.GetSqlSugarClient()) { var i = db.Deleteable<T>().In(ids).ExecuteCommand(); return i > 0; } } #endregion } }
如今,倉儲接口和泛型倉儲基類已建立好了,接下來咱們重構 IPostRepository 和 PostRepository,使他們分別繼承自 IRepository 和 GenericRepository。
IPostRepository.cs
using TsBlog.Domain.Entities; namespace TsBlog.Repositories { public interface IPostRepository :IRepository<Post> { } }
PostRepository.cs
using TsBlog.Domain.Entities; namespace TsBlog.Repositories { /// <summary> /// POST表的數據庫操做類 /// </summary> public class PostRepository : GenericRepository<Post> { } }
IPostRepository 和 PostRepository 是否是一下簡潔了不少,但實現的方法仍是和重構前是同樣的。
怎麼樣,若是咱們再新增用戶表的倉儲接口和倉儲實現是否是很是簡單了呢?不再用爲重複的增,刪,改,查操做來複制,粘貼了。
在項目【TsBlog.Repositories】中添加接口類 IDependency.cs :
namespace TsBlog.Repositories { /// <summary> /// 依賴注入的接口約束 /// </summary> public interface IDependency { } }
在泛型倉儲抽象基類 GenericRepository.cs 中添加 IDependency 接口約束 :
public abstract class GenericRepository<T> : IDependency, IRepository<T> where T : class, new()
打開項目【TsBlog.Frontend】中的 Global.asax 從新配置 AutofacRegister 方法,以下:
private void AutofacRegister() { var builder = new ContainerBuilder(); //註冊MvcApplication程序集中全部的控制器 builder.RegisterControllers(typeof(MvcApplication).Assembly); //註冊倉儲層服務 //builder.RegisterType<PostRepository>().As<IPostRepository>(); //註冊基於接口約束的實體 var assembly = AppDomain.CurrentDomain.GetAssemblies(); builder.RegisterAssemblyTypes(assembly) .Where( t => t.GetInterfaces() .Any(i => i.IsAssignableFrom(typeof(IDependency))) ) .AsImplementedInterfaces() .InstancePerDependency(); //註冊服務層服務 builder.RegisterType<PostService>().As<IPostService>(); //註冊過濾器 builder.RegisterFilterProvider(); var container = builder.Build(); //設置依賴注入解析器 DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); }
按F5運行,是否報錯了?
是的,由於咱們剛纔修改了泛型倉儲中Insert的返回類型,因此,修改 IPostService.cs中的Insert的返回類型爲long:
long Insert(Post entity);
修改後的 IPostService.cs:
using System.Collections.Generic; using TsBlog.Domain.Entities; namespace TsBlog.Services { public interface IPostService { /// <summary> /// 根據ID查詢單條數據 /// </summary> /// <param name="id">ID</param> /// <returns></returns> Post FindById(int id); /// <summary> /// 查詢全部數據(無分頁,大數量時請慎用) /// </summary> /// <returns></returns> IEnumerable<Post> FindAll(); /// <summary> /// 寫入實體數據 /// </summary> /// <param name="entity">博文實體類</param> /// <returns></returns> long Insert(Post entity); /// <summary> /// 更新實體數據 /// </summary> /// <param name="entity">博文實體類</param> /// <returns></returns> bool Update(Post entity); /// <summary> /// 根據實體刪除一條數據 /// </summary> /// <param name="entity">博文實體類</param> /// <returns></returns> bool Delete(Post entity); /// <summary> /// 刪除指定ID的數據 /// </summary> /// <param name="id">主鍵ID</param> /// <returns></returns> bool DeleteById(object id); /// <summary> /// 刪除指定ID集合的數據(批量刪除) /// </summary> /// <param name="ids">主鍵ID集合</param> /// <returns></returns> bool DeleteByIds(object[] ids); } }
再修改 PostService.cs中的Insert的返回類型爲long:
public long Insert(Post entity) { return _postRepository.Insert(entity); }
修改後的 PostService.cs:
using System.Collections.Generic; using TsBlog.Domain.Entities; using TsBlog.Repositories; namespace TsBlog.Services { public class PostService : IPostService { private readonly IRepository<Post> _postRepository; public PostService(IRepository<Post> postRepository) { _postRepository = postRepository; } public bool Delete(Post entity) { return _postRepository.Delete(entity); } public bool DeleteById(object id) { return _postRepository.DeleteById(id); } public bool DeleteByIds(object[] ids) { return _postRepository.DeleteByIds(ids); } public IEnumerable<Post> FindAll() { return _postRepository.FindAll(); } public Post FindById(int id) { return _postRepository.FindById(id); } public long Insert(Post entity) { return _postRepository.Insert(entity); } public bool Update(Post entity) { return _postRepository.Update(entity); } } }
請注意:在 PostRepository.cs中尚未繼承至 IPostRepository.cs ,因此,在 PostService.cs 的構造函數中咱們暫時使用泛型接口 IRepository<T>:
private readonly IRepository<Post> _postRepository; public PostService(IRepository<Post> postRepository)
_postRepository = postRepository;
}
下一篇將解決這個問題 再次按F5運行,打開頁面[http://localhost:54739/home/post],熟悉你頁面又回來了,哈哈。。。 ![create-aspnet-mvc-5-web-application-repository-autofac-automapper-sqlsugar-step-by-step-06][2] 本文的源碼託管地址:https://github.com/lampo1024/TsBlog/releases/tag/v1.6 本文學習到此結束,本系列未完待續,咱們下期再見…… 若是你喜歡Rector的本系列文章,請爲我點個大大的贊。 本文來源 [碼友網][3] 《[一步一步建立ASP.NET MVC5程序\[Repository+Autofac+Automapper+SqlSugar\](六)][4]》 [1]: http://codedefault.com/p/create-aspnet-mvc-5-web-application-repository-autofac-automapper-sqlsugar-step-by-step-05 [2]: http://statics.codedefault.com/uploads/2017/12/create-aspnet-mvc-5-web-application-repository-autofac-automapper-sqlsugar-step-by-step-05-05.png [3]: http://codedefault.com