.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