一步一步建立ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](六)

前言

你們好,我是Rectorgit

又是星期五,很興奮,很高興,很high...啦啦啦。。。
Rector在碼友網又和你們見面啦!!!上一篇《一步一步建立ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](五)》,咱們完成了:github

  • AutoMapper是什麼簡述
  • 安裝AutoMapper
  • AutoMapper的配置
  • AutoMapper的應用

經過前面幾篇文章的學習,本系列【一步一步建立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
    }
}

如今,倉儲接口和泛型倉儲基類已建立好了,接下來咱們重構 IPostRepositoryPostRepository,使他們分別繼承自 IRepositoryGenericRepository

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>
    {
       
    }
}

IPostRepositoryPostRepository 是否是一下簡潔了不少,但實現的方法仍是和重構前是同樣的。

怎麼樣,若是咱們再新增用戶表的倉儲接口和倉儲實現是否是很是簡單了呢?不再用爲重複的增,刪,改,查操做來複制,粘貼了。

配置基於接口的依賴注入

在項目【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
相關文章
相關標籤/搜索