1. 程式人生 > >.Net Core3.0 WebApi 專案框架搭建 五: 輕量型ORM+非同步泛型倉儲

.Net Core3.0 WebApi 專案框架搭建 五: 輕量型ORM+非同步泛型倉儲

.Net Core3.0 WebApi 專案框架搭建:目錄

 

SqlSugar介紹

 

SqlSugar是國人開發者開發的一款基於.NET的ORM框架,是可以執行在.NET 4.+ & .NET CORE的高效能、輕量級 ORM框架,眾多.NET框架中最容易使用的資料庫訪問技術。官網http://www.codeisbug.com/Doc/8

 

SqlSugar的優點:

 

1、高效能 ,不誇張的說,去掉Sql在資料庫執行的時間,SqlSugar是EF數倍效能,另外在批量操作和一對多查詢上也有不錯的SQL優化

 

2、高擴充套件性 ,支援自定義拉姆達函式解析、擴充套件資料型別、支援自定義實體特性,外部快取等

 

3、穩定性和技術支援,  雖然不是官方ORM, 但在穩定性上也是有著數年使用者積累,如果遇到問題可以在GITHUB提出來,會根據緊急度定期解決

 

4、功能全面,雖然SqlSugar小巧可功能並不遜色於EF框架

 

5、創新、持續更新 ,向下相容

建立資料庫

這裡採用DB First的模式,先新建一個數據庫,然後新建一張User表,這裡比較簡單,記得表字段添加註釋說明。

 

使用程式碼生成器生成資料庫連線檔案和實體類

下載地址 :https://github.com/sunkaixuan/SoEasyPlatform

用法非常簡單

1、下載專案

2、解壓專案

3、點選解決方案開啟專案

4、配置連線字串名稱、資料庫型別和解決方案名稱

 5、F5執行該專案

 

6.生成成功 

 Repository 和Model層中引入SqlSugar

直接在類庫中通過Nuget引入 sqlSugarCore或者通過Install-Package sqlSugarCore安裝

刪除原來Model層的的User.cs將程式碼生成器生成的實體放到model層的enity資料夾

using System;
using System.Linq;
using System.Text;
using SqlSugar;

namespace Webapi.Core.Model.Enity
{
    ///<summary>
    ///使用者表
    ///</summary>
    [SugarTable("User")]
    public partial class User
    {
        public User()
        {


        }
        /// <summary>
        /// Desc:使用者ID
        /// Default:
        /// Nullable:False
        /// </summary>           
        [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
        public int UserId { get; set; }

        /// <summary>
        /// Desc:使用者名稱
        /// Default:
        /// Nullable:True
        /// </summary>           
        public string UserName { get; set; }

        /// <summary>
        /// Desc:年齡
        /// Default:
        /// Nullable:True
        /// </summary>           
        public int? Age { get; set; }

    }
}

Repository層新建suger資料夾,將生成的DBConext.cs放置進去,裡面已經內建了增刪改查等方法,可以刪除掉這些方法,後面我們自己使用非同步實現,還是很方便的,不過,如果要使用非同步,就要非同步到底,不然就會阻塞,變成了同步。

using Webapi.Core.Model.Entity;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
public class DbContext<T> where T : class, new()
{
    public DbContext()
    {
        Db = new SqlSugarClient(new ConnectionConfig()
        {
            ConnectionString = "server=.;uid=sa;pwd=sa123;database=CoreDB",
            DbType = DbType.SqlServer,
            InitKeyType = InitKeyType.Attribute,//從特性讀取主鍵和自增列資訊
            IsAutoCloseConnection = true,//開啟自動釋放模式和EF原理一樣我就不多解釋了

        });
        //調式程式碼 用來列印SQL 
        Db.Aop.OnLogExecuting = (sql, pars) =>
        {
            Console.WriteLine(sql + "\r\n" +
                Db.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));
            Console.WriteLine();
        };

    }
    //注意:不能寫成靜態的
    public SqlSugarClient Db;//用來處理事務多表查詢和複雜的操作
    public SimpleClient<T> CurrentDb { get { return new SimpleClient<T>(Db); } }//用來操作當前表的資料

   public SimpleClient<User> UserDb { get { return new SimpleClient<User>(Db); } }//用來處理User表的常用操作


   /// <summary>
    /// 獲取所有
    /// </summary>
    /// <returns></returns>
    public virtual List<T> GetList()
    {
        return CurrentDb.GetList();
    }

    /// <summary>
    /// 根據表示式查詢
    /// </summary>
    /// <returns></returns>
    public virtual List<T> GetList(Expression<Func<T, bool>> whereExpression)
    {
        return CurrentDb.GetList(whereExpression);
    }


    /// <summary>
    /// 根據表示式查詢分頁
    /// </summary>
    /// <returns></returns>
    public virtual List<T> GetPageList(Expression<Func<T, bool>> whereExpression, PageModel pageModel)
    {
        return CurrentDb.GetPageList(whereExpression, pageModel);
    }

    /// <summary>
    /// 根據表示式查詢分頁並排序
    /// </summary>
    /// <param name="whereExpression">it</param>
    /// <param name="pageModel"></param>
    /// <param name="orderByExpression">it=>it.id或者it=>new{it.id,it.name}</param>
    /// <param name="orderByType">OrderByType.Desc</param>
    /// <returns></returns>
    public virtual List<T> GetPageList(Expression<Func<T, bool>> whereExpression, PageModel pageModel, Expression<Func<T, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
    {
        return CurrentDb.GetPageList(whereExpression, pageModel,orderByExpression,orderByType);
    }


    /// <summary>
    /// 根據主鍵查詢
    /// </summary>
    /// <returns></returns>
    public virtual T GetById(dynamic id)
    {
        return CurrentDb.GetById(id);
    }

    /// <summary>
    /// 根據主鍵刪除
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public virtual bool Delete(dynamic id)
    {
        return CurrentDb.Delete(id);
    }


    /// <summary>
    /// 根據實體刪除
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public virtual bool Delete(T data)
    {
        return CurrentDb.Delete(data);
    }

    /// <summary>
    /// 根據主鍵刪除
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public virtual bool Delete(dynamic[] ids)
    {
        return CurrentDb.AsDeleteable().In(ids).ExecuteCommand()>0;
    }

    /// <summary>
    /// 根據表示式刪除
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public virtual bool Delete(Expression<Func<T, bool>> whereExpression)
    {
        return CurrentDb.Delete(whereExpression);
    }


    /// <summary>
    /// 根據實體更新,實體需要有主鍵
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public virtual bool Update(T obj)
    {
        return CurrentDb.Update(obj);
    }

    /// <summary>
    ///批量更新
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public virtual bool Update(List<T> objs)
    {
        return CurrentDb.UpdateRange(objs);
    }

    /// <summary>
    /// 插入
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public virtual bool Insert(T obj)
    {
        return CurrentDb.Insert(obj);
    }


    /// <summary>
    /// 批量
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public virtual bool Insert(List<T> objs)
    {
        return CurrentDb.InsertRange(objs);
    }


    //自已擴充套件更多方法 
}

這裡的ConnectionString是資料庫連線字串,我們可以寫在配置檔案裡面,sugar新建BaseDBConfig.cs

    public class BaseDBConfig
    {
        /// <summary>
        /// 資料庫連線字串
        /// </summary>
        public static string ConnectionString { get; set; }

    }

修改DbContext的建構函式

        Db = new SqlSugarClient(new ConnectionConfig()
        {
            ConnectionString = BaseDBConfig.ConnectionString,
            DbType = DbType.SqlServer,
            InitKeyType = InitKeyType.Attribute,//從特性讀取主鍵和自增列資訊
            IsAutoCloseConnection = true,//開啟自動釋放模式和EF原理一樣我就不多解釋了

        });

在 startup.cs 中的 ConfigureServices() 方法中新增

            //資料庫配置
            BaseDBConfig.ConnectionString = Configuration.GetSection("AppSettings:ConnectionString").Value;

設計倉儲基類介面——IBaseRepository.cs

IRepository 層中新增Base資料夾,並新增介面 IBaseRepository.cs。

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace Webapi.Core.IRepository.Base
{
    /// <summary>
    /// 基類介面,其他介面繼承該介面
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
   public interface IBaseRepository<TEntity> where TEntity : class
    {
        /// <summary>
        /// 根據ID查詢
        /// </summary>
        /// <param name="objId"></param>
        /// <returns></returns>
        Task<TEntity> QueryByID(object objId);

        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        Task<bool> Add(TEntity model);

        /// <summary>
        /// 修改
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        Task<bool> Update(TEntity model);

        /// <summary>
        /// 刪除
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        Task<bool> DeleteByIds(object[] ids);

    }
}

繼承基介面

IRepository 層中,將其他的介面,繼承Base,新建IUserRepository.cs,然後將其他所有的方法都繼承該基類方法

   public interface IUserRepository : IBaseRepositoryy<User>
    {

    }

對倉儲基介面進行實現

Repository 層中,新增Base資料夾,並新增 BaseRepository.cs 基類

    public class BaseRepository<TEntity> : DbContext<TEntity>, IBaseRepository<TEntity> where TEntity : class, new()
    {
        /// <summary>
        /// 寫入實體資料
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<bool> Add(TEntity model)
        {
            var i = await Task.Run(() => Db.Insertable(model).ExecuteReturnBigIdentity());
            //返回的i是long型別,這裡你可以根據你的業務需要進行處理
            return i;
        }

        /// <summary>
        /// 根據ID刪除
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public async Task<bool> DeleteByIds(object[] ids)
        {
            var i = await Task.Run(() => Db.Deleteable<TEntity>().In(ids).ExecuteCommand());
            return i > 0;
        }

        /// <summary>
        /// 根據ID查詢一條資料
        /// </summary>
        /// <param name="objId"></param>
        /// <returns></returns>
        public async Task<TEntity> QueryByID(object objId)
        {
            return await Task.Run(() => Db.Queryable<TEntity>().InSingle(objId));
        }

        /// <summary>
        /// 更新實體資料
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<bool> Update(TEntity model)
        {
            //這種方式會以主鍵為條件
            var i = await Task.Run(() => Db.Updateable(model).ExecuteCommand());
            return i > 0;
        }
Repository層新建UserRepository,繼承BaseRepository和IUserRepository
    public class UserRepository : BaseRepository<User>, IUserRepository
    {

    }

業務邏輯層基類與基介面

IService 層中新增Base資料夾,並新增介面 IBaseService.cs。

public interface IBaseServices<TEntity> where TEntity : class
    {
        /// <summary>
        /// 根據ID列表刪除
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        Task<bool> DeleteByIds(object[] ids);

        /// <summary>
        /// 根據ID查詢
        /// </summary>
        /// <param name="objId"></param>
        /// <returns></returns>
        Task<TEntity> QueryByID(object objId);

        /// <summary>
        /// 新增實體
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        Task<bool> Add(TEntity model);

        /// <summary>
        /// 更新實體
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>

        Task<bool> Update(TEntity model);
    }

Service 層中新增Base資料夾,並新增介面 BaseService.cs。並新增 BaseService.cs 基類

    public class BaseServices<TEntity> : IBaseServices<TEntity> where TEntity : class, new()
    {
        public IBaseRepository<TEntity> baseDal = new BaseRepository<TEntity>();

        /// <summary>
        /// 寫入實體
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<bool> Add(TEntity model)
        {
            return await baseDal.Add(model);
        }

        /// <summary>
        /// 根據ID刪除
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>

        public async Task<bool> DeleteByIds(object[] ids)
        {
            return await baseDal.DeleteByIds(ids);
        }

        /// <summary>
        /// 根據ID查詢
        /// </summary>
        /// <param name="objId"></param>
        /// <returns></returns>
        public async Task<TEntity> QueryByID(object objId)
        {
            return await baseDal.QueryByID(objId);
        }

        /// <summary>
        /// 更新實體
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<bool> Update(TEntity model)
        {
            return await baseDal.Update(model);
        }
    }

IService 層新建IUserService,繼承BaseService

    public interface IUserService : IBaseService<User>
    {

    }

Service 層新建IUserService,繼承BaseService和IUserService

    public class UserService : BaseService<User>, IUserService
    {

    }

新增介面

User控制器新增介面:

 /// <summary>
        /// 根據id獲取資料
        /// </summary>
        /// <param name="id">引數id</param>
        /// <returns></returns>
        [HttpGet("{id}", Name = "Get")]
        public async Task<IActionResult> GetUser(int id)
        {
            IUserService userService = new UserService();
            User user = await userService.QueryByID(id);
            return Ok(user);
        }


        /// <summary>
        /// 新增資料
        /// </summary>
        /// <param name="id">引數id</param>
        /// <returns></returns>
        [HttpGet("{id}", Name = "Get")]
        public async Task<IActionResult> Add(User user)
        {
            IUserService userService = new UserService();
            var count = await userService.Add(user);
            return Ok(count);
        }

        /// <summary>
        /// 更新資料
        /// </summary>
        /// <param name="id">引數id</param>
        /// <returns></returns>
        [HttpGet("{id}", Name = "Get")]
        public async Task<IActionResult> Update(User user)
        {
            IUserService userService = new UserService();
            var sucess = await userService.Update(user);
            return Ok(sucess);
        }

        /// <summary>
        /// 刪除資料
        /// </summary>
        /// <param name="id">引數id</param>
        /// <returns></returns>
        [HttpGet("{id}", Name = "Get")]
        public async Task<IActionResult> Delete(object[] ids)
        {
            IUserService userService = new UserService();
            var sucess = await userService.DeleteByIds(ids);
            return Ok(sucess);
        }

除錯介面

F5執行專案,測試新增介面:

 資料庫成功添加了資料,因為Id用的是自增,所以是1

 測試查詢介面:

 測試修改介面

如果修改不存在的ID,則刪除失敗

 測試刪除介面:

 資料已刪除

 本章Github

 https://github.com/huguodong/Webapi.Core/tree/sqlsu