net core Webapi基礎工程搭建(六)——數據庫操做_Part 1

前言

後端開發最常打交道的就是數據庫了(靜態網站靠邊),上一篇net core Webapi基礎工程搭建(五)——緩存機制,緩存就是爲了減小數據庫的讀操做,不過什麼訪問都是會耗時的,拿空間(內存)換時間對用戶體驗來講是慣用手段,後續介紹界面操做的時候再說用戶體驗。sql

SqlSugar

固然你能夠用EF(過重,擴展性相對差,但不能否認基本上涵蓋範圍夠廣),也能夠用Dapper(這個我以前頭一回鼓搗net core的時候用的是Dapper),或者本身基於原生去寫數據庫的操做,都Ok,可是若是有造好的輪子,對於咱們來講用就好了,能夠深刻理解但對於常規開發來講,CV大法是最好的(新手向),SqlSugar文檔地址數據庫

以前的工程在最初建立的時候,沒有建立完整,由於當時不操做數據層,因此偷個懶,此次一併建立,具體過程再也不贅述
,同April.Util工程的建立一致,都是類庫項目,新建April.ServiceApril.Entity後端

好了,咱們在Service與Entity項目中經過NuGet包引入sqlSugarCore,至於緣由前面也說過net core Webapi基礎工程搭建(四)——日誌功能log4netapi

這裏應該不須要再圖文介紹引入了,若是不清楚,也能夠去上面的連接查看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; }
    }

實體對象我就很少寫了,重複的工做是根據你本身的業務所處理的。函數

Service層

這個地方我重點標註下,是由於數據庫這塊兒的操做仍是須要重視的,咱們先來新建個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();
        }
    }

構造函數主要用於實例化你的數據庫對象(鏈接串,數據庫類型),日誌的記錄,事務這些也都標註上,後續能夠替換直接使用。

BaseService(基類)

在最初寫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介紹具體的用法和測試吧。

相關文章
相關標籤/搜索