目錄html
後端開發最常打交道的就是數據庫了(靜態網站靠邊),上一篇net core Webapi基礎工程搭建(五)——緩存機制,緩存就是爲了減小數據庫的讀操做,不過什麼訪問都是會耗時的,拿空間(內存)換時間對用戶體驗來講是慣用手段,後續介紹界面操做的時候再說用戶體驗。sql
固然你能夠用EF(過重,擴展性相對差,但不能否認基本上涵蓋範圍夠廣),也能夠用Dapper(這個我以前頭一回鼓搗net core的時候用的是Dapper),或者本身基於原生去寫數據庫的操做,都Ok,可是若是有造好的輪子,對於咱們來講用就好了,能夠深刻理解但對於常規開發來講,CV大法是最好的(新手向),SqlSugar的文檔地址。數據庫
以前的工程在最初建立的時候,沒有建立完整,由於當時不操做數據層,因此偷個懶,此次一併建立,具體過程再也不贅述
,同April.Util工程的建立一致,都是類庫項目,新建April.Service,April.Entity。後端
好了,咱們在Service與Entity項目中經過NuGet包引入sqlSugarCore,至於緣由前面也說過net core Webapi基礎工程搭建(四)——日誌功能log4net。api
這裏應該不須要再圖文介紹引入了,若是不清楚,也能夠去上面的連接查看NuGet的引入方法。緩存
引入完成後,咱們在Entity項目建立一個類對象,命名爲StudentEntity吧,只是作個示例。服務器
public class StudentEntity { private int _ID = -1; private string _Name = string.Empty; private string _Number = string.Empty; private int _Age = 0; private int _Sex = 0; private string _Address = string.Empty; }
對象屬性這塊兒,看我的習慣,有些人偏向於直接get,set方法,我習慣於先初始化,選中全部的私有屬性,使用宇宙第一IDE的快捷鍵Ctrl+R+E,點擊肯定,好了本身去加註釋去吧。架構
這裏也說下爲何Entity這個實例對象層也要引入SqlSugar,是由於若是你的表名或者屬性名與數據庫不一致的時候,仍是須要標識出來的,好比下面的代碼,具體的用法仍是去參考文檔吧,我這只是輕描淡寫下。app
[SugarTable("test_Student")] public class StudentEntity { private int _ID = -1; private string _Name = string.Empty; private string _Number = string.Empty; private int _Age = 0; private int _Sex = 0; private string _Address = string.Empty; /// <summary> /// 主鍵 /// </summary> [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int ID { get => _ID; set => _ID = value; } /// <summary> /// 姓名 /// </summary> public string Name { get => _Name; set => _Name = value; } /// <summary> /// 學號 /// </summary> public string Number { get => _Number; set => _Number = value; } /// <summary> /// 年齡 /// </summary> public int Age { get => _Age; set => _Age = value; } /// <summary> /// 性別 /// </summary> public int Sex { get => _Sex; set => _Sex = value; } /// <summary> /// 家庭住址 /// </summary> [SugarColumn(ColumnName = "test_Address")] public string Address { get => _Address; set => _Address = value; } }
實體對象我就很少寫了,重複的工做是根據你本身的業務所處理的。函數
這個地方我重點標註下,是由於數據庫這塊兒的操做仍是須要重視的,咱們先來新建個BaseDbContext用於執行數據庫操做的實體。
public class BaseDbContext { public SqlSugarClient Db; /// <summary> /// 構造函數 /// </summary> /// <param name="connStr">數據庫鏈接串</param> /// <param name="sqlType">數據庫類型</param> public BaseDbContext(string connStr, int sqlType = 1) { InitDataBase(connStr, sqlType); } /// <summary> /// 構造函數 /// </summary> /// <param name="serverIp">服務器IP</param> /// <param name="user">用戶名</param> /// <param name="pass">密碼</param> /// <param name="dataBase">數據庫</param> public BaseDbContext(string serverIp, string user, string pass, string dataBase) { string connStr = $"server={serverIp};user id={user};password={pass};persistsecurityinfo=True;database={dataBase}"; InitDataBase(connStr); } /// <summary> /// 初始化數據庫鏈接 /// </summary> /// <param name="listConn">鏈接字符串</param> private void InitDataBase(string connStr, int sqlType = 1) { Db = new SqlSugarClient(new ConnectionConfig() { ConnectionString = connStr, DbType = (DbType)sqlType, IsAutoCloseConnection = true, //SlaveConnectionConfigs = slaveConnectionConfigs }); Db.Ado.CommandTimeOut = 30000;//設置超時時間 Db.Aop.OnLogExecuted = (sql, pars) => //SQL執行完事件 { //這裏能夠查看執行的sql語句跟參數 }; Db.Aop.OnLogExecuting = (sql, pars) => //SQL執行前事件 { //這裏能夠查看執行的sql語句跟參數 }; Db.Aop.OnError = (exp) =>//執行SQL 錯誤事件 { //這裏能夠查看執行的sql語句跟參數 }; Db.Aop.OnExecutingChangeSql = (sql, pars) => //SQL執行前 能夠修改SQL { return new KeyValuePair<string, SugarParameter[]>(sql, pars); }; } /// <summary> /// 開啓事務 /// </summary> public void BeginTran() { Db.Ado.BeginTran(); } /// <summary> /// 提交事務 /// </summary> public void CommitTran() { Db.Ado.CommitTran(); } /// <summary> /// 回滾事務 /// </summary> public void RollbackTran() { Db.Ado.RollbackTran(); } }
構造函數主要用於實例化你的數據庫對象(鏈接串,數據庫類型),日誌的記錄,事務這些也都標註上,後續能夠替換直接使用。
在最初寫net core的時候,我用Repository層來實現sql處理,Service用來作邏輯處理,傳統的三層架構,可是對於簡單的工程來講,我的感受Bll層的存在不是那麼理想,多是我沒完全理解三層架構吧,這個地方若是有我的想法或好的看法也但願一塊交流,互相進步。
在寫基類以前,咱們在Util層新建一個SqlSqlFilterEntity,這步可能算是畫蛇添足,可是爲了減小團隊其餘人的學習成本,我仍是寫了這個對象,以至於後續的封裝,會以此爲參數作傳遞而不公開lambda的寫法使用。
public class SqlFilterEntity { private string _Filter = string.Empty; private Dictionary<string, object> _Value = null; /// <summary> /// 查詢條件 /// </summary> public string Filter { get => _Filter; set => _Filter = value; } /// <summary> /// 查詢參數 /// </summary> public Dictionary<string, object> Value { get => _Value; set => _Value = value; } }
在Service層新建IBaseService接口。
public interface IBaseService<T> : IDisposable { /// <summary> /// 分頁查詢集合 /// </summary> /// <param name="pageIndex">頁碼</param> /// <param name="pageSize">分頁大小</param> /// <param name="strField">查詢字段</param> /// <param name="filter">查詢條件</param> /// <param name="strOrder">排序規則</param> /// <param name="totalCount">總數</param> /// <returns>數據集合</returns> List<T> GetPageList(int pageIndex, int pageSize, string strField, SqlFilterEntity filter, string strOrder, out int totalCount); /// <summary> /// 獲取列表集合 /// </summary> /// <param name="field">查詢字段</param> /// <param name="filter">查詢條件</param> /// <returns>數據集合</returns> ISugarQueryable<T> GetList(string field, SqlFilterEntity filter); /// <summary> /// 獲取列表集合 /// </summary> /// <returns>數據集合</returns> ISugarQueryable<T> GetList(int top = 0); /// <summary> /// 獲取對象 /// </summary> /// <param name="field">查詢字段</param> /// <param name="filter">查詢條件</param> /// <returns>對象</returns> T GetEntity(SqlFilterEntity filter, string field = ""); /// <summary> /// 判斷數據是否存在 /// </summary> /// <param name="filter">查詢條件</param> /// <returns>執行結果</returns> bool IsExists(SqlFilterEntity filter); /// <summary> /// 新增 /// </summary> /// <param name="entity">實例對象</param> /// <param name="ignoreColumns">排除列</param> /// <param name="isLock">是否加鎖</param> /// <returns>自增id</returns> int Insert(T entity, List<string> ignoreColumns = null, bool isLock = false); /// <summary> /// 修改 /// </summary> /// <param name="entity">實例對象</param> /// <param name="ignoreColumns">排除列</param> /// <param name="isLock">是否加鎖</param> /// <returns>執行結果</returns> bool Update(T entity, List<string> ignoreColumns = null, bool isLock = false); /// <summary> /// 根據主鍵刪除 /// </summary> /// <param name="entity">實例對象</param> /// <param name="isLock">是否加鎖</param> /// <returns>執行結果</returns> bool Delete(T entity, bool isLock = false); }
能夠看到,我經過SqlFilterEntity這一實例來傳遞個人Where條件。
實現接口方法,新建BaseService。
public class BaseService<T> : IBaseService<T> where T : class, new() { private BaseDbContext baseDb; protected SqlSugarClient db; public BaseService() { baseDb = new BaseDbContext("你的數據庫鏈接"); db = baseDb.Db; } /// <summary> /// 分頁查詢集合 /// </summary> /// <param name="pageIndex">頁碼</param> /// <param name="pageSize">分頁大小</param> /// <param name="strField">查詢字段</param> /// <param name="filter">查詢條件</param> /// <param name="strOrder">排序規則</param> /// <param name="totalCount">總數</param> /// <returns>數據集合</returns> public List<T> GetPageList(int pageIndex, int pageSize, string strField, SqlFilterEntity filter, string strOrder, out int totalCount) { totalCount = 0; if (pageIndex <= 0) { pageIndex = 1; } if (pageSize <= 0) { pageSize = 10;//暫定默認分頁大小爲10 } if (string.IsNullOrEmpty(strField)) { strField = ""; } if (string.IsNullOrEmpty(strOrder)) { strOrder = string.Format("ID asc");//這個地方我當時是在Config設置默認的排序 } if (filter == null) { filter = new SqlFilterEntity(); } return db.Queryable<T>().With(SqlWith.NoLock).Select(strField).WhereIF(!string.IsNullOrEmpty(filter.Filter), filter.Filter, filter.Value).OrderByIF(!string.IsNullOrEmpty(strOrder), strOrder).ToPageList(pageIndex, pageSize, ref totalCount); } /// <summary> /// 獲取列表集合 /// </summary> /// <param name="field">查詢字段</param> /// <param name="filter">查詢條件</param> /// <returns>數據集合</returns> public ISugarQueryable<T> GetList(string field, SqlFilterEntity filter) { if (string.IsNullOrEmpty(field)) { field = ""; } if (filter == null) { filter = new SqlFilterEntity(); } return db.Queryable<T>().With(SqlWith.NoLock).Select(field).WhereIF(!string.IsNullOrEmpty(filter.Filter), filter.Filter, filter.Value); } /// <summary> /// 獲取列表集合 /// </summary> /// <returns>數據集合</returns> public ISugarQueryable<T> GetList(int top = 0) { if (top > 0) { return db.Queryable<T>().With(SqlWith.NoLock).Take(top); } else { return db.Queryable<T>().With(SqlWith.NoLock); } } /// <summary> /// 獲取對象 /// </summary> /// <param name="field">查詢字段</param> /// <param name="filter">查詢條件</param> /// <returns>對象</returns> public T GetEntity(SqlFilterEntity filter, string field = "") { if (string.IsNullOrEmpty(field)) { field = ""; } if (filter != null) { return db.Queryable<T>().With(SqlWith.NoLock).Select(field).WhereIF(!string.IsNullOrEmpty(filter.Filter), filter.Filter, filter.Value).First(); } return default(T); } /// <summary> /// 判斷數據是否存在 /// </summary> /// <param name="filter">查詢條件</param> /// <returns>執行結果</returns> public bool IsExists(SqlFilterEntity filter) { var result = db.Queryable<T>().With(SqlWith.NoLock).WhereIF(!string.IsNullOrEmpty(filter.Filter), filter.Filter, filter.Value).Count(); return result > 0; } /// <summary> /// 新增 /// </summary> /// <param name="entity">實例對象</param> /// <param name="ignoreColumns">排除列</param> /// <param name="isLock">是否加鎖</param> /// <returns>自增id</returns> public int Insert(T entity, List<string> ignoreColumns = null, bool isLock = false) { if (ignoreColumns == null) { ignoreColumns = new List<string>(); } var result = isLock ? db.Insertable(entity).With(SqlWith.UpdLock).IgnoreColumns(ignoreColumns.ToArray()).ExecuteReturnIdentity() : db.Insertable(entity).IgnoreColumns(ignoreColumns.ToArray()).ExecuteReturnIdentity(); return result; } /// <summary> /// 修改 /// </summary> /// <param name="entity">實例對象</param> /// <param name="ignoreColumns">排除列</param> /// <param name="isLock">是否加鎖</param> /// <returns>執行結果</returns> public bool Update(T entity, List<string> ignoreColumns = null, bool isLock = false) { if (ignoreColumns == null) { ignoreColumns = new List<string>(); } var result = isLock ? db.Updateable(entity).With(SqlWith.UpdLock).IgnoreColumns(ignoreColumns.ToArray()).ExecuteCommand() : db.Updateable(entity).IgnoreColumns(ignoreColumns.ToArray()).ExecuteCommand(); return result > 0; } /// <summary> /// 根據主鍵刪除 /// </summary> /// <param name="entity">實例對象</param> /// <param name="isLock">是否加鎖</param> /// <returns>執行結果</returns> public bool Delete(T entity, bool isLock = false) { var result = isLock ? db.Deleteable<T>(entity).With(SqlWith.RowLock).ExecuteCommand().ObjToBool() : db.Deleteable<T>(entity).ExecuteCommand().ObjToBool(); return result; } public void Dispose() { } }
這一篇感受寫的很少,可是代碼放的有點兒多,習慣性的把東西儘量介紹詳細點兒,萬一有人真的從小白開始一點點兒想折騰個啥東西呢(好比說我),下一篇Part 2介紹具體的用法和測試吧。