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

来源:https://www.cnblogs.com/bobositlife/archive/2018/01/26/create-aspnet-mvc-5-web-application-repository-autofac-automapper-sqlsugar-step-by-step-06.html
-Advertisement-
Play Games

前言 大家好,我是Rector 又是星期五,很興奮,很高興,很high...啦啦啦。。。 Rector在圖享網又和大家見面啦!!!上一篇《 "一步一步創建ASP.NET MVC5程式\[Repository+Autofac+Automapper+SqlSugar\" ][1]》,我們完成了: Aut ...


前言

大家好,我是Rector

又是星期五,很興奮,很高興,很high...啦啦啦。。。
Rector在圖享網又和大家見面啦!!!上一篇《一步一步創建ASP.NET MVC5程式[Repository+Autofac+Automapper+SqlSugar](五)》,我們完成了:

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

通過前面幾篇文章的學習,本系列【一步一步創建ASP.NET MVC5程式[Repository+Autofac+Automapper+SqlSugar]】中主要涉及到的技術和組件已基本介紹到位了。接下來的系列文章主要會以知識技術整合,提升,重構等為中心來展開,通過解決項目實戰遇到的各種問題來幫助大家有目,有方向性地學習,以達到提升大家的ASP.NENT MVC 5開發技能的效果。

本文知識要點

今天要給大家分享的是本系列[一步一步創建ASP.NET MVC5程式]的 進階知識

  • 泛型倉儲

為什麼使用泛型倉儲

說到為什麼使用泛型倉儲,我們不得不回到我們的項目,以項目設計來驅動,說明為什麼是泛型倉儲,用泛型倉儲有哪些好處。

回到項目本身

在v1.5版本中,我們已經實現了倉儲層和服務層。其中,倉儲層是我們直接訪問資料庫的層,可以通過倉儲層對資料庫進行任何有許可權的操作,包括增,刪,改,查。我們的PostRepository博文倉儲實現類已經實現了其介面中的增,刪,改,查操作,IPostRepository介面:

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文件中呢?同時,其實現也要同樣的複製。

如果我們又添加在資料庫新增了多張表,對應的倉儲介面和實現是不是又要重覆以上的操作呢?ctrl+c , ctrl+v !!! 如果是這樣,還不如使用代碼生成器來得快。

看到這裡,希望有開發經驗的開發者們不要笑話。回想一下當初筆者在初入.NET開發的時候也是這麼乾的,複製,粘貼,代碼生成器都用過。隨著時間和經驗的積累,你也會變得更好,前提是少用或者不用複製,粘貼來實現編碼功能,即使是網上找的實現方法,也要自己動手敲一遍。

以上兩段話跑題了,我們還是切回正題,上面提到的問題其實是有辦法來避免重覆工作,減輕我們的工作量的,即使用泛型倉儲

泛型倉儲的實現

首先,打開項目【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

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

本文的源碼托管地址:https://github.com/lampo1024/TsBlog/releases/tag/v1.6

本文學習到此結束,本系列未完待續,我們下期再見……

如果你喜歡Rector的本系列文章,請為我點個大大的贊。

本文來源 圖享網一步一步創建ASP.NET MVC5程式[Repository+Autofac+Automapper+SqlSugar](六)


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 最近在開發應用的過程中,我遇到瞭如標題所述的需求,其實主要是為了能夠快捷啟動應用,正像我們可以在“運行”對話框中可以輸入一些可執行程式的名稱後,就能夠直接啟動它;這樣做,可以增加 App 的易用性。在查了一些文檔後,得知在 Windows Build 16266 之後,就加入相關的 API,因此要實 ...
  • cmd regedit打開註冊表,進入到[HKEY_USERS\.DEFAULT\Control Panel\International] ,然後1、將鍵 sDate 的值由 / 改為 - 2、將鍵 sShortDate 的值由 yyyy/M/d 改為 yyyy-M-d (註:如果是yyyy/M/d ...
  • 這是一個使用js實現登錄、緩衝動畫以及頁面跳轉的例子。不需要用到資料庫、不需要複雜的邏輯、更不需要千行的代碼;只需要幾個簡單的標簽、幾張GIF格式的圖片、再加上幾行代碼就能實現以上功能。本文主要有三個HTML頁面構成,一個登錄頁面、一個載入緩衝頁面、最後一個是緩衝過後的首頁。為了做這個GIF圖,隨即 ...
  • 假設以下場景,如果在客戶端運行程式,最的事情之一是有一個響應的用戶界面。這意味著無論應用程式發生什麼,所有的用戶界面元素都要保持 快速運行,用戶能夠從應用程式得到快速響應。達到這一點並不容易!如果你嘗試在Windows系統中打開記事本並載入一個有幾兆大小的文檔,應用程式視窗將交結一段的時間,因為整個... ...
  • 演示產品源碼下載地址:http://www.jinhusns.com ...
  • 在對接華為NB-IoT平臺時用到了https連接方式, 華為方面提供了crt格式的證書文件, 但官方只給了java範例, C#引用該證書時出現了問題, 下麵是踩的坑: NB_IoT平臺介面調試, https認證方式 NB_IoT平臺介面調試, https認證方式 首先在代碼中加入 1 Service ...
  • ...
  • 全國天氣預報 全國城市天氣預報,包含直轄市,省(港澳台),市,區,縣3級。 可查詢半月天氣預報。 支持定製多個城市。 下載地址:https://pan.baidu.com/s/1mjFeOPE ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...