2.簡單的搭建後端,一步一步從基礎開始(2023-9-20優化更新第一次)

来源:https://www.cnblogs.com/zhang-3/archive/2023/09/18/17709227.html
-Advertisement-
Play Games

上傳Git的忽略文件下載 千萬不能忘記配置忽略文件,不然可能會搞得你一個項目10多個G,很煩人 先梳理下我們需要新建的項目如下。介面層一般I(i)開頭,實現層不需要。後面還會增加擴展類或者其他的。 API程式層:FastEasyAPI 服務介面層:FastEasy.IService 服務實現層:Fa ...


上傳Git的忽略文件下載

千萬不能忘記配置忽略文件,不然可能會搞得你一個項目10多個G,很煩人


先梳理下我們需要新建的項目如下。介面層一般I(i)開頭,實現層不需要。後面還會增加擴展類或者其他的。

API程式層:FastEasyAPI

服務介面層:FastEasy.IService

服務實現層:FastEasy.Service

倉儲介面層:FastEasy.IRepository

倉儲實現層:FastEasy.Repository

實體層:FastEasy.Model

 倉儲模式的介紹很多大佬都有博客可以瞭解,我不會說什麼太專業的辭彙表達,我也記不得,我會按照我自己的理解來形容

首先,倉儲層(介面+實現),服務層(介面+實現),API程式層。這算是三層的結構,如果熟練或者精通了,不用建這麼多類庫,介面實現層可以合併或者使用泛型倉儲…讓項目短小精悍,不過目前我還理解不夠,所以搭建最基礎的倉儲模式。

接下來應該去添加訪問資料庫的對象

 這個就有很多選擇了。Ado,ef,Sqlsugar等等。我剛出來工作的時候學的ado和ef,現在的話……唉,正如前文所說,一路cv過來的,現在都忘的差不多了。所以我選擇Sqlsugar!推薦!很棒!反正公司老項目就用他們封裝好的ef或者ado,如果有新項目需求,我都用sqlsugar,真的好用一批~特別是多租戶事務之類的,我很喜歡~(有點跑題了,繼續……)

原本我打算直接用來著,後來突然想起來,咱們都core了,怎麼可以不用依賴註入呢?所以嘞,這裡先穿插一下Autofac的使用,因為之前我單獨寫過autofac的教程,所以可能我會粘貼之前的文章內容,不懂的話可以留言或者百度,面向百度編程,是你最好的選擇!

Autofac的使用  Sqlsugar的註入使用

 在api程式層引入autofac的包:Autofac.Extensions.DependencyInjection(內置依賴包含了autofac的基礎包)

這裡說下經驗之談,也不是我自己的經驗,就是隨著項目越來越大,Programs裡面的服務註冊會越來越多,所有我要在程式下麵新建一個文件夾Filter,裡面放我的各個模塊的註冊類,例如我要註入Sqlsugar,那我會在filter文件夾下新建一個類,起名:SqlsugarModule。然後關於Sqlsugar的註入配置都寫在此處,然後Programs里直接註入這個類就行,這樣後期不會因為註入很多東西導致Programs過於臃腫。

引入Sqlsugar 的包:SqlSugarCore。第一次接觸的話推薦大家去官網學習

  Services.AddSingleton<ISqlSugarClient>(s =>
        {
            SqlSugarScope db = new(new ConnectionConfig()
            {
                DbType = SqlSugar.DbType.Sqlite,
                ConnectionString = "DataSource=sqlsugar-dev.db",
                IsAutoCloseConnection = true,
            });
            return db;
        });

 

scope單例註入,client非單例註入。官網的介紹是scope線程安全,排查問題方便,client非單例模式,性能比scope高5%左右。我是覺得性能差不多,scope可以讓我省心很多,嘿嘿嘿。

到這裡的話,sqlsugar其實已經註入完成了,就是這麼簡單,操作比ef方便很多啊,不過這種東西都是唯手熟爾,哪個你用著6就用哪個

創建基礎Base基類

寫到這兒發現前面的autofac說早了。抱歉各位。因為sqlsugar實在是很簡單,所以完全不需要用到autofac(笑死),不過都這樣了,就沒辦法了,反正下麵肯定會再說autofac的使用的。

上面註入了Sqlsuar的服務,代表著我們可以訪問資料庫了。

眾所周知,所有的功能需求到最後無非都是對資料庫的增刪改查,我們先不討論你業務邏輯怎麼搞,到最後你無非都是要搞一個實體,對資料庫新增,或者修改,或者搞一個id對著資料庫刪除數據。因此,無論你操作哪個表,都離不開這些增刪改查,所以這個Base基層,就是所有基礎的增刪改查,分頁查詢等。

簡單梳理下結構,首先我們有倉儲層,服務層,應用程式層。倉儲層和服務層都各有一個介面層和實現層。最基本的要新增4個類:IBaseRepository,BaseRepository。IBaseService,BaseRepository。因為對數據訪問在倉儲層,所以我們從Repository開始新建起:先介面後實現。(Base基層的倉儲層和服務層基本上一模一樣,其方法也只是滿足基本的增刪改查需求,若是複雜邏輯還需將基類定義為虛方法,在每張表獨立的倉儲層和服務層去重寫方法)

基礎方法囊括:單條增刪改查,批量增刪改查,分頁查詢

 這是倉儲層的Base基類介面

    /// <summary>
    /// 1條新增
    /// </summary>
    /// <param name="entity">要創建的實體對象</param>
    /// <returns>如果成功創建實體記錄,則返回 true;否則返回 false。</returns>
    Task<bool> CreateEntityAsync(T entity);

    /// <summary>
    /// 批量新增
    /// </summary>
    /// <param name="entities">要新增的實體對象集合</param>
    /// <returns>新增操作影響的記錄條數</returns>
    Task<int> CreateEntitysAsync(List<T> entitys);

    /// <summary>
    /// 1條修改
    /// </summary>
    /// <param name="entity">要修改的實體對象</param>
    /// <returns>如果成功修改實體記錄,則返回 true;否則返回 false。</returns>
    Task<bool> UpdateEntityAsync(T entity);

    /// <summary>
    /// 批量修改
    /// </summary>
    /// <param name="entities">要修改的實體對象集合</param>
    /// <returns>受影響的記錄數</returns>

    Task<int> UpdateEntitysAsync(List<T> entitys);

    /// <summary>
    /// 1條刪除
    /// </summary>
    /// <param name="id">要刪除的記錄的主鍵ID。</param>
    /// <returns>刪除操作影響的記錄數。</returns>
    Task<bool> DeleteEntityByIdAsync(int id);

    /// <summary>
    /// 根據條件批量刪除
    /// </summary>
    /// <param name="expression">條件</param>
    /// <returns>返回受影響條數</returns>
    Task<int> DeleteEntitysByWhereAsync(Expression<Func<T, bool>> expression);

    /// <summary>
    /// 查詢所有
    /// </summary>
    /// <returns>返回實體集合</returns>
    Task<List<T>> GetEntitysAsync();

    /// <summary>
    /// 根據ID單條查詢
    /// </summary>
    /// <param name="id">主鍵ID</param>
    /// <returns>查詢到的實體</returns>
    Task<T> GetEntityByIdAsync(int id);

    /// <summary>
    /// 根據條件批量查詢。
    /// </summary>
    /// <param name="expression">條件表達式</param>
    /// <returns>符合條件的實體集合</returns>
    Task<List<T>> GetEntitysByWhereAsync(Expression<Func<T, bool>> expression);

    /// <summary>
    /// 分頁查詢
    /// </summary>
    /// <param name="pageNumber">頁碼,從1開始</param>
    /// <param name="pageSize">每頁條數</param>
    /// <param name="totalCount">總記錄數</param>
    /// <returns>查詢到的實體集合</returns>
    Task<List<T>> GetEntitysToPageAsync(int pageNumber, int pageSize, ref int totalCount);
View Code

 

 這是倉儲層Base基類實現。實現的是上面定義的Base基類介面

public class BaseRepository<T> : IBaseRepository<T> where T : class, new()
{
    #region 構造

    public BaseRepository(ISqlSugarClient _db)
    {
        db = _db;
    }

    #endregion 構造

    protected readonly ISqlSugarClient db;

    public virtual async Task<bool> CreateEntityAsync(T entity)
    {
        try
        {
            return await db.Insertable<T>(entity).ExecuteCommandAsync() > 0;
        }
        catch (Exception)
        {
            return false;
        }
    }

    public virtual async Task<int> CreateEntitysAsync(List<T> entitys)
    {
        try
        {
            return await db.Insertable<T>(entitys).ExecuteCommandAsync();
        }
        catch (Exception)
        {
            return 0;
        }
    }

    public virtual async Task<bool> DeleteEntityByIdAsync(int id)
    {
        try
        {
            return await db.Deleteable<T>().In(id).ExecuteCommandAsync() > 0;
        }
        catch (Exception)
        {
            return false;
        }
    }

    public virtual async Task<int> DeleteEntitysByWhereAsync(Expression<Func<T, bool>> expression)
    {
        try
        {
            return await db.Deleteable<T>().Where(expression).ExecuteCommandAsync();
        }
        catch (Exception)
        {
            return 0;
        }
    }

    public virtual async Task<T> GetEntityByIdAsync(int id)
    {
        try
        {
            return await db.Queryable<T>().InSingleAsync(id);
        }
        catch (Exception)
        {
            return null;
        }
    }

    public virtual async Task<List<T>> GetEntitysAsync()
    {
        try
        {
            return await db.Queryable<T>().ToListAsync();
        }
        catch (Exception)
        {
            return null;
        }
    }

    public virtual async Task<List<T>> GetEntitysByWhereAsync(Expression<Func<T, bool>> expression)
    {
        try
        {
            return await db.Queryable<T>().Where(expression).ToListAsync();
        }
        catch (Exception)
        {
            return null;
        }
    }

    public virtual List<T> GetEntitysToPage(int pageNumber, int pageSize, ref int totalCount)
    {
        try
        {
            return db.Queryable<T>().ToPageList(pageNumber, pageSize, ref totalCount);
        }
        catch (Exception)
        {
            return null;
        }
    }

    public virtual async Task<bool> UpdateEntityAsync(T entity)
    {
        try
        {
            return await db.Updateable<T>(entity).ExecuteCommandAsync() > 0;
        }
        catch (Exception)
        {
            return false;
        }
    }

    public virtual async Task<int> UpdateEntitysAsync(List<T> entitys)
    {
        try
        {
            return await db.Updateable<T>(entitys).ExecuteCommandAsync();
        }
        catch (Exception)
        {
            return 0;
        }
    }
}
View Code

 

 基礎的增刪改差不多就這麼多了。寫的時候發現個小問題。就是根據id的增刪改查,其實也沒必要專門搞個方法,使用條件查詢方法就可以了,不過一開始沒考慮到,我覺得代碼復用性高一點說明寫的好,不過我這個並沒什麼太大影響。繼續~~

服務層的Base基類介面,這個完全可以複製倉儲層的base基類介面,不能說毫無關係,只能說完全一樣,所以這裡不寫咯。

服務層的Base基類實現,也差不多一樣,不同的是倉儲層是使用db訪問資料庫,而服務層是通過構造函數註入倉儲層的Base基類介面,通過調用介面方法來進行調用。

public class BaseService<T> : IBaseService<T> where T : class, new()
{
    #region 構造

    public BaseService(IBaseRepository<T> _baseRepository)
    {
        baseRepository = _baseRepository;
    }

    #endregion 構造

    protected readonly IBaseRepository<T> baseRepository;

    public Task<bool> CreateEntityAsync(T entity)
    {
        return baseRepository.CreateEntityAsync(entity);
    }

    public Task<int> CreateEntitysAsync(List<T> entitys)
    {
        return baseRepository.CreateEntitysAsync(entitys);
    }

    public Task<bool> DeleteEntityByIdAsync(int id)
    {
        return baseRepository.DeleteEntityByIdAsync(id);
    }

    public Task<int> DeleteEntitysByWhereAsync(Expression<Func<T, bool>> expression)
    {
        return baseRepository.DeleteEntitysByWhereAsync(expression);
    }

    public Task<T> GetEntityByIdAsync(int id)
    {
        return baseRepository.GetEntityByIdAsync(id);
    }

    public Task<List<T>> GetEntitysAsync()
    {
        return baseRepository.GetEntitysAsync();
    }

    public Task<List<T>> GetEntitysByWhereAsync(Expression<Func<T, bool>> expression)
    {
        return baseRepository.GetEntitysByWhereAsync(expression);
    }

    public List<T> GetEntitysToPage(int pageNumber, int pageSize, ref int totalCount)
    {
        return baseRepository.GetEntitysToPage(pageNumber, pageSize, ref totalCount);
    }

    public Task<bool> UpdateEntityAsync(T entity)
    {
        return baseRepository.UpdateEntityAsync(entity);
    }

    public Task<int> UpdateEntitysAsync(List<T> entitys)
    {
        return baseRepository.UpdateEntitysAsync(entitys);
    }
}
View Code

 

看到這裡的話,基本的倉儲模式已經搭建完成了,是的沒錯,就是這麼簡單。但是還沒有真正的去添加資料庫,所以只有基層,像這種普通的倉儲模式有個很麻煩的地方就是每一個表結構至少要在項目里添加4個類,所以還是比較麻煩的,所以最近在研究代碼生成,網上有很多現成的代碼生成器,不過我還是想自己研究研究,為了我這個開源項目的目標!我要搞個適配我這個項目的代碼生成器,畢竟自己寫的代碼我心裡有數~

都要一起加油喲~ 掰掰~


 

2023-9-20第一次更新內容:

有小伙伴建議我增加原生Sql的查詢,確實如此,所以在寫完代碼生成的文章後,我又在base基類添加了三個介面,分別是:

  1. 原生SQL查詢,返回List集合
  2. 原生SQL查詢,返回Datatable
  3. 存儲過程查詢,返回Datatable

 


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

-Advertisement-
Play Games
更多相關文章
  • 用Rust手把手編寫一個Proxy(代理), 動工 項目 ++wmproxy++ gitee 傳送門 github 傳送門 設計流程圖 flowchart LR A[客戶端] -->|Http| B[代理端] --> C[代理服務端] --> D[服務端] B -->|直達| D A -->|Htt ...
  • 在學習C#中的記錄類型時,對出現的Equals和ReferenceEquals得到的不同結果表示不理解,隨即進行相關資料查找。 值類型 == : 比較兩者的“內容”是否相同,即“值”是否一樣Equals:比較兩者的“內容”是否相同,即“值”是否一樣ReferenceEquals:返回false,因為 ...
  • 生成者/消費者概念編程模型 通道是生成者/使用者概念編程模型的實現。 在此編程模型中,生成者非同步生成數據,使用者非同步使用該數據。 換句話說,此模型將數據從一方移交給另一方。 嘗試將通道視為任何其他常見的泛型集合類型,例如 List。 主要區別在於,此集合管理同步,並通過工廠創建選項提供各種消耗模型。 ...
  • 在做某個報表管理功能時,有一個需求:需要根據自定義配置的[周起始日]來統計上周、本周的訂單數據。在C#中並沒有封裝的方法根據我們需要來直接獲取上一周某天到某天、本周某天到某天,所以需要我們自己封裝方法來實現(我們也可以按照這個思路使用其他語言來實現)。 ...
  • 前言 百度AI是指百度公司的人工智慧技術全稱。它採用深度學習技術,包括自然語言處理、語音識別、電腦視覺、知識圖譜等,可應用於各個領域如互聯網、醫療、金融、教育、汽車、物流等。百度AI的發展將幫助人類更好地理解世界和提高生活品質,接下來就通過一個小案例演示實現百度AI在文字和圖像敏感審核應用。 項目 ...
  • ASP.NET Core應用程式現在是一個控制台應用程式,在Windows上直接雙擊啟動,但如果想讓開發完成的ASP.NET Core應用程式開機啟動,可以將ASP.NET Core應用程式修改成Windows服務運行,但這需要額外添加代碼,也可以使用IIS來托管ASP.NET Core應用程式,但 ...
  • swagger介面一多,還是需要分個組比較妥當,以圖文方式看更直觀 定義分組 添加分組 看板展示 兩個分組 我要對v1組進行隱藏,首先先瞭解一下 ApplicationModel ApplicationModel描述了應用中的各種對象和行為,包含Application、Controller、Acti ...
  • 近些年來,隨著WPF在生產,製造,工業控制等領域應用越來越廣發,很多企業對WPF開發的需求也逐漸增多,使得很多人看到潛在機會,不斷從Web,WinForm開發轉向了WPF開發,但是WPF開發也有很多新的概念及設計思想,如:數據驅動,數據綁定,依賴屬性,命令,控制項模板,數據模板,MVVM等,與傳統Wi... ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...