本文3.0版本文章
本文涉及的內容,同樣適用於3.0版本,不用修改。
前言
1、在使用的時候,特別是更新數據的時候,如果不知道哪里有問題,可以查看數據庫 和 實體類 的字段,是否大小寫一致,比如 name 和 Name
2、在使用Sqlsugar 的 CodeFirst的時候,記得要先重建一個空的數據庫,不然會提示錯誤。
注意:Sqlsugar 5.x 版本已經支持自動創建數據庫了,如果你用了最新的版本,可以不用手動創建(加上一行代碼 db.DbMaintenance.CreateDatabase(); ),反之需要;
3、要學會使用數據庫監控分析器
書接上文:《從壹開始前后端分離【 .NET Core2.0 Api + Vue 2.0 + AOP + 分布式】框架之六 || API項目整體搭建 6.1 倉儲》,我們簡單的對整體項目進行搭建,用到了項目中常見的倉儲模式+面向接口編程,核心的一共是六層,當然你也可以根據自己的需求進行擴展,比如我在其他的項目中會用到Common層,當然我們這個項目接下來也會有,或者我還會添加Task層,主要是作為定時項目使用,我之前用的是Task Schedule,基本能滿足需求。
在上一節中,我們最后提出了兩個問題,不知道大家是否還記得,這里還重新說明一下:
1、如果每個倉儲文件都需要把一個一個寫出來,至少是四遍,會不會太麻煩,而且無法復用,失去了面向接口編程的意義;
2、每次接口調用的時候,需要引入很多命名空間,比如Blog.Core.IServices;Blog.Core.Services;Blog.Core.Repository等等
對就是這兩個問題,相信聰明的大家也都能看懂,或許還能給出相應的解決辦法,比如泛型倉儲,比如依賴注入,當然,如果你有更好的辦法,歡迎留言,我會把你的想法寫下了,讓大家一起進步。這里先簡單說下問題1中為什么要四遍,倉儲模式的基本就是如何將持久化動作和對象獲取方式以及領域模型Domain Model結合起來,進一步:如何更加統一我們的語言(Ubiquitous Language),一個整合持久化技術的好辦法是倉儲Repositories。明白了這個問題,你就知道,定義倉儲,首先需要定義IRepository接口(1),然后再Repository中實現(2),接着在IService層中引用這些接口,同時也可以自定義擴展業務邏輯接口(3),最后在Service層中去實現(4),這就是四層。
問題明白了,我們就要動手做起來,思考了下,如果干巴巴直接寫泛型倉儲,會比較干澀,所以我考慮今天先把數據持久化做出來,一個輕量級的ORM框架——SqlSugar。
零、今天完成的藍色部分
0、創建實體模型與數據庫
1、實體模型
在上篇文章中,我們說到了倉儲模式,所謂倉儲,就是對數據的管理,因此,我們就必須要有實體模型,下文說到了 Advertisement ,那就先創建它的實體模型,其他的相關模型,大家自行下載代碼即可:
public class Advertisement { /// <summary> /// ID /// </summary>public int Id { get; set; } /// <summary> /// 廣告圖片 /// </summary>public string ImgUrl { get; set; } /// <summary> /// 廣告標題 /// </summary>public string Title { get; set; } /// <summary> /// 廣告鏈接 /// </summary>public string Url { get; set; } /// <summary> /// 備注 /// </summary>public string Remark { get; set; } /// <summary> /// 創建時間 /// </summary> public DateTime Createdate { get; set; } = DateTime.Now; }
2、創建數據庫
既然要操作數據庫,肯定得先有一個數據庫,這里提供了兩種方式:
1、Sql語句生成(目前已經不更新,如果一定想要,去群文件下載)
2、通過我的項目,code first 生成,並且里邊可以直接 seed data,這樣就能生成一個完整的帶數據的Database。
具體如何操作可以查看文章——《支持多種數據庫 & 快速數據庫生成》,如果你感覺麻煩,就自己根據上邊的實體模型,自己創建一個數據庫。
一、在 IRepository 層設計接口
還記得昨天我們實現的Sum接口么,今天在倉儲接口 IAdvertisementRepository.cs 添加CURD四個接口,首先需要將Model層添加引用,這個應該都會,以后不再細說,如下:
namespace Blog.Core.IRepository { public interface IAdvertisementRepository { int Sum(int i, int j); int Add(Advertisement model); bool Delete(Advertisement model); bool Update(Advertisement model); List<Advertisement> Query(Expression<Func<Advertisement, bool>> whereExpression); } }
編譯項目,提示錯誤,別慌!很正常,因為我們現在只是添加了接口,還沒有實現接口。
二、在 Repository 層實現相應接口
當然,我們還是在AdvertisementRepository.cs文件中操作,這里我有一個小技巧,不知道大家是否用到過,因為我比較喜歡寫接口,這樣不僅可以不暴露核心代碼,而且也可以讓用戶調用的時候,直接看到簡單的接口方法列表,而不去管具體的實現過程,這樣的設計思路還是比較提倡的,如下圖:
你先看到了繼承的接口有紅色的波浪線,證明有錯誤,然后右鍵該接口,點擊 Quick Actions and Refactorings...,也就是 快速操作和重構 ,你就會看到VS的智能提示,雙擊左側的Implement interface,也就是實現接口,如下圖:
Visual Studio真是宇宙第一IDE,沒的說 [手動點贊],然后就創建成功了,你就可以去掉throw處理,自定義代碼編寫了,當然,如果你不習慣或者害怕出錯,那就手動寫吧,也是很快的。
namespace Blog.Core.Repository { public class AdvertisementRepository : IAdvertisementRepository { public int Add(Advertisement model) { throw new NotImplementedException(); } public bool Delete(Advertisement model) { throw new NotImplementedException(); } public List<Advertisement> Query(Expression<Func<Advertisement, bool>> whereExpression) { throw new NotImplementedException(); } public int Sum(int i, int j) { return i + j; } public bool Update(Advertisement model) { throw new NotImplementedException(); } } }
這個時候我們重新編譯項目,嗯!意料之中,沒有錯誤,但是具體的數據持久化如何寫呢?
三、引用輕量級的ORM框架——SqlSugar
首先什么是ORM, 對象關系映射(Object Relational Mapping,簡稱ORM)模式是一種為了解決面向對象與關系數據庫存在的互不匹配的現象的技術。簡單的說,ORM是通過使用描述對象和數據庫之間映射的元數據,將程序中的對象自動持久化到關系數據庫中。這些概念我就不細說了,自從開發這些年,一直在討論的問題就是用ADO.NET還是用ORM框架,還記得前幾年面試的時候,有一個經理問:
如果一個項目,你是用三層架構ADO,還是用ORM中的EF?
大家可以自由留言,我表示各有千秋吧,一個產品的存在即有合理性,我平時項目中也有ADO,也有EF,不過本系列教程中基於面向對象思想,面向接口思想,當然還有以后的面向切面編程(AOP),還是使用ORM框架,不過是一個輕量級的,EF比較重,我在我其他的項目中用到了.Net MVC 6.0 + EF Code First 的項目,如果大家需要,我也開源出去,放在Github上,請文末留言吧~
關於ORM有一些常見的框架,如SqlSugar、Dapper、EF、NHeberneit等等,這些我都或多或少的了解過,使用過,至於你要問我為啥用SqlSugar,只要一個原因,作者是中國人,嗯!沒錯,這里給他打個廣告,本系列中的前端框架Vue,也是我們中國的,Vue作者尤雨溪,這里也祝福大家都能有自己的成績,為國人爭光!
扯遠了,開始動手引入框架:
開始,我們需要先向 Repository 層中引入SqlSugar,如下:
1)直接在類庫中通過Nuget引入 sqlSugarCore,一定是Core版本的!,我個人采用這個辦法,因為項目已經比較成型
2)Github下載源碼,然后項目引用(點擊跳轉到Github下載頁)
注意:為什么要單獨在倉儲層來引入ORM持久化接口,是因為,降低耦合,如果以后想要換成EF或者Deper,只需要修改Repository就行了,其他都不需要修改,達到很好的解耦效果。
編譯一切正常,繼續
首先呢,你需要了解下sqlsugar的具體使用方法,http://www.codeisbug.com/Doc/8,你先自己在控制台可以簡單試一試,這里就不細說了,如果大家有需要,我可以單開一個文章,重點講解SqlSugar這一塊。
我的正式項目中,這個連接字符串已經修改,統一放到了 Common 層的 DB 文件夾下了,不過你依然可以按照我文章提示的自己寫,也可以直接看我的Github代碼,但是請不要問我,為什么兩者不一樣了。
1、在Blog.Core.Repository新建一個sugar文件夾,然后添加兩個配置文件,BaseDBConfig.cs 和 DbContext.cs ,這個你如果看了上邊的文檔,那這兩個應該就不是問題。
namespace Blog.Core.Repository { public class BaseDBConfig { public static string ConnectionString = File.ReadAllText(@"D:\my-file\dbCountPsw1.txt").Trim(); //正常格式是 //public static string ConnectionString = "server=.;uid=sa;pwd=sa;database=BlogDB"; //原諒我用配置文件的形式,因為我直接調用的是我的服務器賬號和密碼,安全起見 } }
//DbContext.cs,一個詳細的上下文類,看不懂沒關系,以后我會詳細講解

namespace Blog.Core.Repository { public class DbContext { private static string _connectionString; private static DbType _dbType; private SqlSugarClient _db; /// <summary> /// 連接字符串 /// Blog.Core /// </summary> public static string ConnectionString { get { return _connectionString; } set { _connectionString = value; } } /// <summary> /// 數據庫類型 /// Blog.Core /// </summary> public static DbType DbType { get { return _dbType; } set { _dbType = value; } } /// <summary> /// 數據連接對象 /// Blog.Core /// </summary> public SqlSugarClient Db { get { return _db; } private set { _db = value; } } /// <summary> /// 數據庫上下文實例(自動關閉連接) /// Blog.Core /// </summary> public static DbContext Context { get { return new DbContext(); } } /// <summary> /// 功能描述:構造函數 /// 作 者:Blog.Core /// </summary> private DbContext() { if (string.IsNullOrEmpty(_connectionString)) throw new ArgumentNullException("數據庫連接字符串為空"); _db = new SqlSugarClient(new ConnectionConfig() { ConnectionString = _connectionString, DbType = _dbType, IsAutoCloseConnection = true, IsShardSameThread = true, ConfigureExternalServices = new ConfigureExternalServices() { //DataInfoCacheService = new HttpRuntimeCache() }, MoreSettings = new ConnMoreSettings() { //IsWithNoLockQuery = true, IsAutoRemoveDataCache = true } }); } /// <summary> /// 功能描述:構造函數 /// 作 者:Blog.Core /// </summary> /// <param name="blnIsAutoCloseConnection">是否自動關閉連接</param> private DbContext(bool blnIsAutoCloseConnection) { if (string.IsNullOrEmpty(_connectionString)) throw new ArgumentNullException("數據庫連接字符串為空"); _db = new SqlSugarClient(new ConnectionConfig() { ConnectionString = _connectionString, DbType = _dbType, IsAutoCloseConnection = blnIsAutoCloseConnection, IsShardSameThread = true, ConfigureExternalServices = new ConfigureExternalServices() { //DataInfoCacheService = new HttpRuntimeCache() }, MoreSettings = new ConnMoreSettings() { //IsWithNoLockQuery = true, IsAutoRemoveDataCache = true } }); } #region 實例方法 /// <summary> /// 功能描述:獲取數據庫處理對象 /// 作 者:Blog.Core /// </summary> /// <returns>返回值</returns> public SimpleClient<T> GetEntityDB<T>() where T : class, new() { return new SimpleClient<T>(_db); } /// <summary> /// 功能描述:獲取數據庫處理對象 /// 作 者:Blog.Core /// </summary> /// <param name="db">db</param> /// <returns>返回值</returns> public SimpleClient<T> GetEntityDB<T>(SqlSugarClient db) where T : class, new() { return new SimpleClient<T>(db); } #region 根據數據庫表生產實體類 /// <summary> /// 功能描述:根據數據庫表生產實體類 /// 作 者:Blog.Core /// </summary> /// <param name="strPath">實體類存放路徑</param> public void CreateClassFileByDBTalbe(string strPath) { CreateClassFileByDBTalbe(strPath, "Km.PosZC"); } /// <summary> /// 功能描述:根據數據庫表生產實體類 /// 作 者:Blog.Core /// </summary> /// <param name="strPath">實體類存放路徑</param> /// <param name="strNameSpace">命名空間</param> public void CreateClassFileByDBTalbe(string strPath, string strNameSpace) { CreateClassFileByDBTalbe(strPath, strNameSpace, null); } /// <summary> /// 功能描述:根據數據庫表生產實體類 /// 作 者:Blog.Core /// </summary> /// <param name="strPath">實體類存放路徑</param> /// <param name="strNameSpace">命名空間</param> /// <param name="lstTableNames">生產指定的表</param> public void CreateClassFileByDBTalbe( string strPath, string strNameSpace, string[] lstTableNames) { CreateClassFileByDBTalbe(strPath, strNameSpace, lstTableNames, string.Empty); } /// <summary> /// 功能描述:根據數據庫表生產實體類 /// 作 者:Blog.Core /// </summary> /// <param name="strPath">實體類存放路徑</param> /// <param name="strNameSpace">命名空間</param> /// <param name="lstTableNames">生產指定的表</param> /// <param name="strInterface">實現接口</param> public void CreateClassFileByDBTalbe( string strPath, string strNameSpace, string[] lstTableNames, string strInterface, bool blnSerializable = false) { if (lstTableNames != null && lstTableNames.Length > 0) { _db.DbFirst.Where(lstTableNames).IsCreateDefaultValue().IsCreateAttribute() .SettingClassTemplate(p => p = @" {using} namespace {Namespace} { {ClassDescription}{SugarTable}" + (blnSerializable ? "[Serializable]" : "") + @" public partial class {ClassName}" + (string.IsNullOrEmpty(strInterface) ? "" : (" : " + strInterface)) + @" { public {ClassName}() { {Constructor} } {PropertyName} } } ") .SettingPropertyTemplate(p => p = @" {SugarColumn} public {PropertyType} {PropertyName} { get { return _{PropertyName}; } set { if(_{PropertyName}!=value) { base.SetValueCall(" + "\"{PropertyName}\",_{PropertyName}" + @"); } _{PropertyName}=value; } }") .SettingPropertyDescriptionTemplate(p => p = " private {PropertyType} _{PropertyName};\r\n" + p) .SettingConstructorTemplate(p => p = " this._{PropertyName} ={DefaultValue};") .CreateClassFile(strPath, strNameSpace); } else { _db.DbFirst.IsCreateAttribute().IsCreateDefaultValue() .SettingClassTemplate(p => p = @" {using} namespace {Namespace} { {ClassDescription}{SugarTable}" + (blnSerializable ? "[Serializable]" : "") + @" public partial class {ClassName}" + (string.IsNullOrEmpty(strInterface) ? "" : (" : " + strInterface)) + @" { public {ClassName}() { {Constructor} } {PropertyName} } } ") .SettingPropertyTemplate(p => p = @" {SugarColumn} public {PropertyType} {PropertyName} { get { return _{PropertyName}; } set { if(_{PropertyName}!=value) { base.SetValueCall(" + "\"{PropertyName}\",_{PropertyName}" + @"); } _{PropertyName}=value; } }") .SettingPropertyDescriptionTemplate(p => p = " private {PropertyType} _{PropertyName};\r\n" + p) .SettingConstructorTemplate(p => p = " this._{PropertyName} ={DefaultValue};") .CreateClassFile(strPath, strNameSpace); } } #endregion #region 根據實體類生成數據庫表 /// <summary> /// 功能描述:根據實體類生成數據庫表 /// 作 者:Blog.Core /// </summary> /// <param name="blnBackupTable">是否備份表</param> /// <param name="lstEntitys">指定的實體</param> public void CreateTableByEntity<T>(bool blnBackupTable, params T[] lstEntitys) where T : class, new() { Type[] lstTypes = null; if (lstEntitys != null) { lstTypes = new Type[lstEntitys.Length]; for (int i = 0; i < lstEntitys.Length; i++) { T t = lstEntitys[i]; lstTypes[i] = typeof(T); } } CreateTableByEntity(blnBackupTable, lstTypes); } /// <summary> /// 功能描述:根據實體類生成數據庫表 /// 作 者:Blog.Core /// </summary> /// <param name="blnBackupTable">是否備份表</param> /// <param name="lstEntitys">指定的實體</param> public void CreateTableByEntity(bool blnBackupTable, params Type[] lstEntitys) { if (blnBackupTable) { _db.CodeFirst.BackupTable().InitTables(lstEntitys); //change entity backupTable } else { _db.CodeFirst.InitTables(lstEntitys); } } #endregion #endregion #region 靜態方法 /// <summary> /// 功能描述:獲得一個DbContext /// 作 者:Blog.Core /// </summary> /// <param name="blnIsAutoCloseConnection">是否自動關閉連接(如果為false,則使用接受時需要手動關閉Db)</param> /// <returns>返回值</returns> public static DbContext GetDbContext(bool blnIsAutoCloseConnection = true) { return new DbContext(blnIsAutoCloseConnection); } /// <summary> /// 功能描述:設置初始化參數 /// 作 者:Blog.Core /// </summary> /// <param name="strConnectionString">連接字符串</param> /// <param name="enmDbType">數據庫類型</param> public static void Init(string strConnectionString, DbType enmDbType = SqlSugar.DbType.SqlServer) { _connectionString = strConnectionString; _dbType = enmDbType; } /// <summary> /// 功能描述:創建一個鏈接配置 /// 作 者:Blog.Core /// </summary> /// <param name="blnIsAutoCloseConnection">是否自動關閉連接</param> /// <param name="blnIsShardSameThread">是否誇類事務</param> /// <returns>ConnectionConfig</returns> public static ConnectionConfig GetConnectionConfig(bool blnIsAutoCloseConnection = true, bool blnIsShardSameThread = false) { ConnectionConfig config = new ConnectionConfig() { ConnectionString = _connectionString, DbType = _dbType, IsAutoCloseConnection = blnIsAutoCloseConnection, ConfigureExternalServices = new ConfigureExternalServices() { //DataInfoCacheService = new HttpRuntimeCache() }, IsShardSameThread = blnIsShardSameThread }; return config; } /// <summary> /// 功能描述:獲取一個自定義的DB /// 作 者:Blog.Core /// </summary> /// <param name="config">config</param> /// <returns>返回值</returns> public static SqlSugarClient GetCustomDB(ConnectionConfig config) { return new SqlSugarClient(config); } /// <summary> /// 功能描述:獲取一個自定義的數據庫處理對象 /// 作 者:Blog.Core /// </summary> /// <param name="sugarClient">sugarClient</param> /// <returns>返回值</returns> public static SimpleClient<T> GetCustomEntityDB<T>(SqlSugarClient sugarClient) where T : class, new() { return new SimpleClient<T>(sugarClient); } /// <summary> /// 功能描述:獲取一個自定義的數據庫處理對象 /// 作 者:Blog.Core /// </summary> /// <param name="config">config</param> /// <returns>返回值</returns> public static SimpleClient<T> GetCustomEntityDB<T>(ConnectionConfig config) where T : class, new() { SqlSugarClient sugarClient = GetCustomDB(config); return GetCustomEntityDB<T>(sugarClient); } #endregion } }
2、然后在剛剛我們實現那四個方法的AdvertisementRepository.cs中,重寫構造函數,編輯統一Sqlsugar實例方法,用到了私有屬性,為以后的單列模式做准備。
private DbContext context; private SqlSugarClient db; private SimpleClient<Advertisement> entityDB; internal SqlSugarClient Db { get { return db; } private set { db = value; } } public DbContext Context { get { return context; } set { context = value; } } public AdvertisementRepository() { DbContext.Init(BaseDBConfig.ConnectionString); context = DbContext.GetDbContext();
db = context.Db; entityDB = context.GetEntityDB<Advertisement>(db); }
3、正式開始寫持久化邏輯代碼(注意:我在Model層中,添加了全局的數據類型轉換方法,UtilConvert,這樣就不用每次都Convert,而且也解決了為空轉換異常的bug)

public static class UtilConvert { /// <summary> /// /// </summary> /// <param name="thisValue"></param> /// <returns></returns> public static int ObjToInt(this object thisValue) { int reval = 0; if (thisValue == null) return 0; if (thisValue != null && thisValue != DBNull.Value && int.TryParse(thisValue.ToString(), out reval)) { return reval; } return reval; } /// <summary> /// /// </summary> /// <param name="thisValue"></param> /// <param name="errorValue"></param> /// <returns></returns> public static int ObjToInt(this object thisValue, int errorValue) { int reval = 0; if (thisValue != null && thisValue != DBNull.Value && int.TryParse(thisValue.ToString(), out reval)) { return reval; } return errorValue; } /// <summary> /// /// </summary> /// <param name="thisValue"></param> /// <returns></returns> public static double ObjToMoney(this object thisValue) { double reval = 0; if (thisValue != null && thisValue != DBNull.Value && double.TryParse(thisValue.ToString(), out reval)) { return reval; } return 0; } /// <summary> /// /// </summary> /// <param name="thisValue"></param> /// <param name="errorValue"></param> /// <returns></returns> public static double ObjToMoney(this object thisValue, double errorValue) { double reval = 0; if (thisValue != null && thisValue != DBNull.Value && double.TryParse(thisValue.ToString(), out reval)) { return reval; } return errorValue; } /// <summary> /// /// </summary> /// <param name="thisValue"></param> /// <returns></returns> public static string ObjToString(this object thisValue) { if (thisValue != null) return thisValue.ToString().Trim(); return ""; } /// <summary> /// /// </summary> /// <param name="thisValue"></param> /// <param name="errorValue"></param> /// <returns></returns> public static string ObjToString(this object thisValue, string errorValue) { if (thisValue != null) return thisValue.ToString().Trim(); return errorValue; } /// <summary> /// /// </summary> /// <param name="thisValue"></param> /// <returns></returns> public static Decimal ObjToDecimal(this object thisValue) { Decimal reval = 0; if (thisValue != null && thisValue != DBNull.Value && decimal.TryParse(thisValue.ToString(), out reval)) { return reval; } return 0; } /// <summary> /// /// </summary> /// <param name="thisValue"></param> /// <param name="errorValue"></param> /// <returns></returns> public static Decimal ObjToDecimal(this object thisValue, decimal errorValue) { Decimal reval = 0; if (thisValue != null && thisValue != DBNull.Value && decimal.TryParse(thisValue.ToString(), out reval)) { return reval; } return errorValue; } /// <summary> /// /// </summary> /// <param name="thisValue"></param> /// <returns></returns> public static DateTime ObjToDate(this object thisValue) { DateTime reval = DateTime.MinValue; if (thisValue != null && thisValue != DBNull.Value && DateTime.TryParse(thisValue.ToString(), out reval)) { reval = Convert.ToDateTime(thisValue); } return reval; } /// <summary> /// /// </summary> /// <param name="thisValue"></param> /// <param name="errorValue"></param> /// <returns></returns> public static DateTime ObjToDate(this object thisValue, DateTime errorValue) { DateTime reval = DateTime.MinValue; if (thisValue != null && thisValue != DBNull.Value && DateTime.TryParse(thisValue.ToString(), out reval)) { return reval; } return errorValue; } /// <summary> /// /// </summary> /// <param name="thisValue"></param> /// <returns></returns> public static bool ObjToBool(this object thisValue) { bool reval = false; if (thisValue != null && thisValue != DBNull.Value && bool.TryParse(thisValue.ToString(), out reval)) { return reval; } return reval; } }
最終的倉儲持久化是:
public class AdvertisementRepository : IAdvertisementRepository { private DbContext context; private SqlSugarClient db; private SimpleClient<Advertisement> entityDB; internal SqlSugarClient Db { get { return db; } private set { db = value; } } public DbContext Context { get { return context; } set { context = value; } } public AdvertisementRepository() { DbContext.Init(BaseDBConfig.ConnectionString); context = DbContext.GetDbContext();
db = context.Db; entityDB = context.GetEntityDB<Advertisement>(db); } public int Add(Advertisement model) { //返回的i是long類型,這里你可以根據你的業務需要進行處理 var i = db.Insertable(model).ExecuteReturnBigIdentity(); return i.ObjToInt(); } public bool Delete(Advertisement model) { var i = db.Deleteable(model).ExecuteCommand(); return i > 0; } public List<Advertisement> Query(Expression<Func<Advertisement, bool>> whereExpression) { return entityDB.GetList(whereExpression); } public int Sum(int i, int j) { return i + j; } public bool Update(Advertisement model) { //這種方式會以主鍵為條件 var i = db.Updateable(model).ExecuteCommand(); return i > 0; } }
四、在 IServices 層設計服務接口,並 Service 層實現
這里不細說,記得添加引用,最終的代碼是:
namespace Blog.Core.IServices { public interface IAdvertisementServices { int Sum(int i, int j); int Add(Advertisement model); bool Delete(Advertisement model); bool Update(Advertisement model); List<Advertisement> Query(Expression<Func<Advertisement, bool>> whereExpression); } }
namespace Blog.Core.Services { public class AdvertisementServices : IAdvertisementServices { public IAdvertisementRepository dal = new AdvertisementRepository(); public int Sum(int i, int j) { return dal.Sum(i, j); } public int Add(Advertisement model) { return dal.Add(model); } public bool Delete(Advertisement model) { return dal.Delete(model); } public List<Advertisement> Query(Expression<Func<Advertisement, bool>> whereExpression) { return dal.Query(whereExpression); } public bool Update(Advertisement model) { return dal.Update(model); } } }
都是很簡單,如果昨天的Sum方法你會了,這個肯定都會。
五、Controller測試接口
實現工作,根據id獲取數據
這里為了調試方便,我把權限驗證暫時注釋掉
//[Authorize(Policy ="Admin")]
然后修改我們的其中一個Get方法,根據id獲取信息
// GET: api/Blog/5 /// <summary> /// /// </summary> /// <param name="id"></param> /// <returns></returns> [HttpGet("{id}", Name = "Get")] public List<Advertisement> Get(int id) { IAdvertisementServices advertisementServices = new AdvertisementServices(); return advertisementServices.Query(d => d.Id == id); }
接下來運行調試,在我們接口文檔中,直接點擊調試
得到的結果是如果,雖然是空的,但是返回結果http代碼是200,因為表中沒數據嘛
六、結語
好啦,今天的講解就到這里,你簡單的了解了什么是ORM,以及其中的SqlSugar,然后呢,倉儲模式的具體使用,最后還有真正的連接數據庫,獲取到數據,下一節中,我們繼續來解決兩大問題,來實現泛型倉儲。