ASP.NET CORE API 第三篇 項目整體搭建 異步泛型倉儲+依賴注入初探

原文作者:老張的哲學

回顧

1、Sqlsugar 的使用

在上文中,遇到了大家見仁見智的評論和批評,嗯~說實話,積極性稍微受到了一丟丟的打擊,不過還好,還是有很多很多很多人的贊同的,所以會一直堅持下去,歡迎提出各種建議,問題,意見等,我這個系列呢,只是一個拋磚引玉的文章,大家可以自定義的去擴展學習,比如你看了.net core api,可以自學.net core mvc呀;看了sqlsugar,可以自學EFCore,Deppar呀;看了vue,可以自學React、Angular呀,我希望起到的是一個志同道合的作用,而不是情緒的宣泄場所。🌹

書接上文,《框架之七 || API項目整體搭建 6.2 輕量級ORM》,在文中,我們提到了Sqlsugar,該框架呢我也是諮詢了身邊的一些大佬,他們給我說法是:

Sqlsugar 和 EFCore 一樣,只是一個表達式樹,不用寫sql,但是支持sql,支持多種類型數據庫(MSSQL,Oracle,Mysql,SQLite),配置簡單;

僅僅是一個數據訪問層,100k輕量級,方便遷移;

而且也要看自己公司需要,我司項目也用EFCore ,當然也有部分用的是 SqlSugar,不存在孰優孰劣;

關於速率呢,我簡單的做了一個測試,使用公司的數據表,一共4千萬條數據,我遍歷全表,並提取前一萬條(當然數據庫有主鍵索引,一般分頁100條也夠多了吧),一共1.6s,截圖如下:

image

2、修改數據連接字符串

1、在appsettings.json 中添加

 

"AppSettings": {
"SqlServerConnection": "Server=.;Database=BlogDB;User ID=sa;Password=sa;",
"ProviderName": "System.Data.SqlClient"
},

2、在 startup.cs 中的 ConfigureServices() 方法中添加

//數據庫配置
BaseDBConfig.ConnectionString = Configuration.GetSection("AppSettings:SqlServerConnection").Value;

3、修改BaseDBConfig.cs

public static string ConnectionString { get; set; }

我在之後的項目中會使用他的這個方法,並且做一個擴展 Blog.Common 層 -> Helper -> Appsettings.cs 的 ,這裏先寫上,如果大家都有好的意見或建議,我都會在下一篇文章中寫出來,大家一起學習。

好啦,昨天已經總結好了,開始今天的講解。

在上一節中,我們實現了倉儲層的構造,並聯通了數據庫,調取了數據,整理搭建已經有了一個雛形,今天就繼續往下探討,寫一個異步泛型倉儲

使用異步Async/Aswait呢,還是很方便的,不過,如果要使用異步,就要異步到底,不然就會阻塞,變成了同步,還是鼓勵大家練習下,就算是出現錯誤了,那就證明學習到了,哈哈哈[哭笑];

泛型呢,用到的是接口和基類,可以極大的減少工作量;

今天要完成的淺紫色部分

image.png

一、設計倉儲基類接口——IBaseRepository.cs

這裏說一下,可能有一部分小夥伴是直接跳着看的,所以突然看到這裏,對項目結構並不能很好的理解,可以參考之前的文章:《框架之六 || API項目整體搭建 6.1 倉儲+服務+抽象接口模式

在Blog.Core.IRepository 層中添加BASE文件夾,並添加接口 IBaseRepository.cs

我自己從SimpleClient中,抽取了基本的常見方法做封裝,你也可以自己自定義封裝擴展,有人問我,既然Sqlsugar都已經封裝好了SimpleClient,爲什麼我還要在倉儲中再一次封裝,我是這麼想的,如果一個項目中來了一個新人,之前用過EF或者Sqlhelper,那他來了,需要在重新學習一遍Sqlsugar了,這個時間上,至少一兩天吧,所以封裝基本的接口後,他只需要按照之前的開發方法使用就行,不需要了解底層,當然這個還是個小栗子,其實大公司都是這樣的,更新迭代很快,沒有精力重新學習,所以這也就是面向接口編程的好處,我曾經在微軟的項目中就充分的感受到這個境況。

注意:我這裏沒有封裝多表查詢,其實是可以寫的,參考地址 (多表查詢)如果各位會封裝的話,可以留言,感激不盡**。


 

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace Blog.Core.IRespository.Base
{
    public interface IBaseRespository<TEntity> where TEntity : class
    {
        Task<TEntity> QueryByID(object objId);
        Task<TEntity> QueryByID(object objId,bool blnUseCache = false);
        Task<int> Add(TEntity model);
        Task<bool> DeleteById(object id);
        Task<bool> Delete(TEntity model);
        Task<bool> DeleteByIds(object[] ids);
        Task<bool> Update(TEntity model);
        Task<bool> Update(TEntity entity, string strWhere);
        Task<bool> Update(TEntity entity, List<string> lstColumns = null, List<string> lstIgnoreColumns = null, string strWhere = "");
        Task<List<TEntity>> Query();
        Task<List<TEntity>> Query(string strWhere);
        Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression);
        Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, string strOrderByFileds);
        Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, object>> orderByExpression, bool isAsc = true);
        Task<List<TEntity>> Query(string strWhere, string strOrderByFileds);
        Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, int intTop, string strOrderByFileds);
        Task<List<TEntity>> Query(string strWhere, int intTop, string strOrderByFileds);
        Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, int intPageIndex, int intPageSize, string strOrderByFileds);
        Task<List<TEntity>> Query(string strWhere, int intPageIndex, int intPageSize, string strOrderByFileds);
        Task<List<TEntity>> QueryPage(Expression<Func<TEntity, bool>> whereExpression, int intPageIndex = 0, int intPageSize = 20, string strOrderByFileds = null);
    }
}

二、將其他的倉儲接口,繼承基接口

在Blog.Core.IRepository 層中,將其他的接口,繼承Base。

還記得前幾天我們一直用的IAdvertisementRepository.cs麼,終於可以寫到自身代碼了,繼承Base

image

然後將其他所有的方法都繼承該基類方法,不細說,可以去Github查看。

三、對倉儲基接口進行實現

在Blog.Core.Repository 層中,添加BASE文件夾,並添加 BaseRepository.cs 基類

基本寫法和前幾天的AdvertisementRepository.cs很類似,代碼如下:


 

using Blog.Core.IRepository.Base;
using Blog.Core.Repository;
using Blog.Core.Repository.Sugar;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace Blog.Core.Repository.Base
{
    public class BaseRepository<TEntity> : IBaseRepository<TEntity> where TEntity : class, new()
    {
        private DbContext context;
        private SqlSugarClient db;
        private SimpleClient<TEntity> entityDB;

        public DbContext Context
        {
            get { return context; }
            set { context = value; }
        }

        internal SqlSugarClient Db
        {
            get { return db; }
            private set { db = value; }
        }

        internal SimpleClient<TEntity> EntityDB
        {
            get { return entityDB; }
            private set { entityDB = value; }
        }

        public BaseRepository()
        {
            DbContext.Init(BaseDBConfig.ConnectionString);
            context = DbContext.GetDbContext();
            db = context.Db;
            entityDB = context.GetEntityDB<TEntity>(db);
        }

        public async Task<TEntity> QueryByID(object objId)
        {
            return await Task.Run(() => db.Queryable<TEntity>().InSingle(objId));
        }
        /// <summary>
        /// 功能描述:根據ID查詢一條數據
        /// </summary>
        /// <param name="objId">id(必須指定主鍵特性 [SugarColumn(IsPrimaryKey=true)]),如果是聯合主鍵,請使用Where條件</param>
        /// <param name="blnUseCache">是否使用緩存</param>
        /// <returns>數據實體</returns>
        public async Task<TEntity> QueryByID(object objId, bool blnUseCache = false)
        {
            return await Task.Run(() => db.Queryable<TEntity>().WithCacheIF(blnUseCache).InSingle(objId));
        }

        /// <summary>
        /// 功能描述:根據ID查詢數據
        /// </summary>
        /// <param name="lstIds">id列表(必須指定主鍵特性 [SugarColumn(IsPrimaryKey=true)]),如果是聯合主鍵,請使用Where條件</param>
        /// <returns>數據實體列表</returns>
        public async Task<List<TEntity>> QueryByIDs(object[] lstIds)
        {
            return await Task.Run(() => db.Queryable<TEntity>().In(lstIds).ToList());
        }

        /// <summary>
        /// 寫入實體數據
        /// </summary>
        /// <param name="entity">博文實體類</param>
        /// <returns></returns>
        public async Task<int> Add(TEntity entity)
        {
            var i = await Task.Run(() => db.Insertable(entity).ExecuteReturnBigIdentity());
            //返回的i是long類型,這裏你可以根據你的業務需要進行處理
            return (int)i;
        }

        /// <summary>
        /// 更新實體數據
        /// </summary>
        /// <param name="entity">博文實體類</param>
        /// <returns></returns>
        public async Task<bool> Update(TEntity entity)
        {
            //這種方式會以主鍵爲條件
            var i = await Task.Run(() => db.Updateable(entity).ExecuteCommand());
            return i > 0;
        }

        public async Task<bool> Update(TEntity entity, string strWhere)
        {
            return await Task.Run(() => db.Updateable(entity).Where(strWhere).ExecuteCommand() > 0);
        }

        public async Task<bool> Update(string strSql, SugarParameter[] parameters = null)
        {
            return await Task.Run(() => db.Ado.ExecuteCommand(strSql, parameters) > 0);
        }

        public async Task<bool> Update(TEntity entity,List<string> lstColumns = null,List<string> lstIgnoreColumns = null,string strWhere = "")
        {
            IUpdateable<TEntity> up = await Task.Run(() => db.Updateable(entity));
            if (lstIgnoreColumns != null && lstIgnoreColumns.Count > 0)
            {
                up = await Task.Run(() => up.IgnoreColumns(it => lstIgnoreColumns.Contains(it)));
            }
            if (lstColumns != null && lstColumns.Count > 0)
            {
                up = await Task.Run(() => up.UpdateColumns(it => lstColumns.Contains(it)));
            }
            if (!string.IsNullOrEmpty(strWhere))
            {
                up = await Task.Run(() => up.Where(strWhere));
            }
            return await Task.Run(() => up.ExecuteCommand()) > 0;
        }

        /// <summary>
        /// 根據實體刪除一條數據
        /// </summary>
        /// <param name="entity">博文實體類</param>
        /// <returns></returns>
        public async Task<bool> Delete(TEntity entity)
        {
            var i = await Task.Run(() => db.Deleteable(entity).ExecuteCommand());
            return i > 0;
        }

        /// <summary>
        /// 刪除指定ID的數據
        /// </summary>
        /// <param name="id">主鍵ID</param>
        /// <returns></returns>
        public async Task<bool> DeleteById(object id)
        {
            var i = await Task.Run(() => db.Deleteable<TEntity>(id).ExecuteCommand());
            return i > 0;
        }

        /// <summary>
        /// 刪除指定ID集合的數據(批量刪除)
        /// </summary>
        /// <param name="ids">主鍵ID集合</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>
        /// 功能描述:查詢所有數據
        /// </summary>
        /// <returns>數據列表</returns>
        public async Task<List<TEntity>> Query()
        {
            return await Task.Run(() => entityDB.GetList());
        }

        /// <summary>
        /// 功能描述:查詢數據列表
        /// </summary>
        /// <param name="strWhere">條件</param>
        /// <returns>數據列表</returns>
        public async Task<List<TEntity>> Query(string strWhere)
        {
            return await Task.Run(() => db.Queryable<TEntity>().WhereIF(!string.IsNullOrEmpty(strWhere), strWhere).ToList());
        }

        /// <summary>
        /// 功能描述:查詢數據列表
        /// </summary>
        /// <param name="whereExpression">whereExpression</param>
        /// <returns>數據列表</returns>
        public async Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression)
        {
            return await Task.Run(() => entityDB.GetList(whereExpression));
        }

        /// <summary>
        /// 功能描述:查詢一個列表
        /// </summary>
        /// <param name="whereExpression">條件表達式</param>
        /// <param name="strOrderByFileds">排序字段,如name asc,age desc</param>
        /// <returns>數據列表</returns>
        public async Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, string strOrderByFileds)
        {
            return await Task.Run(() => db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(strOrderByFileds), strOrderByFileds).WhereIF(whereExpression != null, whereExpression).ToList());
        }
        /// <summary>
        /// 功能描述:查詢一個列表
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <param name="orderByExpression"></param>
        /// <param name="isAsc"></param>
        /// <returns></returns>
        public async Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, object>> orderByExpression, bool isAsc = true)
        {
            return await Task.Run(() => db.Queryable<TEntity>().OrderByIF(orderByExpression != null, orderByExpression, isAsc ? OrderByType.Asc : OrderByType.Desc).WhereIF(whereExpression != null, whereExpression).ToList());
        }

        /// <summary>
        /// 功能描述:查詢一個列表
        /// </summary>
        /// <param name="strWhere">條件</param>
        /// <param name="strOrderByFileds">排序字段,如name asc,age desc</param>
        /// <returns>數據列表</returns>
        public async Task<List<TEntity>> Query(string strWhere, string strOrderByFileds)
        {
            return await Task.Run(() => db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(strOrderByFileds), strOrderByFileds).WhereIF(!string.IsNullOrEmpty(strWhere), strWhere).ToList());
        }


        /// <summary>
        /// 功能描述:查詢前N條數據
        /// </summary>
        /// <param name="whereExpression">條件表達式</param>
        /// <param name="intTop">前N條</param>
        /// <param name="strOrderByFileds">排序字段,如name asc,age desc</param>
        /// <returns>數據列表</returns>
        public async Task<List<TEntity>> Query(
            Expression<Func<TEntity, bool>> whereExpression,
            int intTop,
            string strOrderByFileds)
        {
            return await Task.Run(() => db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(strOrderByFileds), strOrderByFileds).WhereIF(whereExpression != null, whereExpression).Take(intTop).ToList());
        }

        /// <summary>
        /// 功能描述:查詢前N條數據
        
        /// </summary>
        /// <param name="strWhere">條件</param>
        /// <param name="intTop">前N條</param>
        /// <param name="strOrderByFileds">排序字段,如name asc,age desc</param>
        /// <returns>數據列表</returns>
        public async Task<List<TEntity>> Query(
            string strWhere,
            int intTop,
            string strOrderByFileds)
        {
            return await Task.Run(() => db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(strOrderByFileds), strOrderByFileds).WhereIF(!string.IsNullOrEmpty(strWhere), strWhere).Take(intTop).ToList());
        }



        /// <summary>
        /// 功能描述:分頁查詢
        /// </summary>
        /// <param name="whereExpression">條件表達式</param>
        /// <param name="intPageIndex">頁碼(下標0)</param>
        /// <param name="intPageSize">頁大小</param>
        /// <param name="strOrderByFileds">排序字段,如name asc,age desc</param>
        /// <returns>數據列表</returns>
        public async Task<List<TEntity>> Query(
            Expression<Func<TEntity, bool>> whereExpression,
            int intPageIndex,
            int intPageSize,
            string strOrderByFileds)
        {
            return await Task.Run(() => db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(strOrderByFileds), strOrderByFileds).WhereIF(whereExpression != null, whereExpression).ToPageList(intPageIndex, intPageSize));
        }

        /// <summary>
        /// 功能描述:分頁查詢
        /// </summary>
        /// <param name="strWhere">條件</param>
        /// <param name="intPageIndex">頁碼(下標0)</param>
        /// <param name="intPageSize">頁大小</param>
        /// <param name="strOrderByFileds">排序字段,如name asc,age desc</param>
        /// <returns>數據列表</returns>
        public async Task<List<TEntity>> Query(
          string strWhere,
          int intPageIndex,
          int intPageSize,

          string strOrderByFileds)
        {
            return await Task.Run(() => db.Queryable<TEntity>().OrderByIF(!string.IsNullOrEmpty(strOrderByFileds), strOrderByFileds).WhereIF(!string.IsNullOrEmpty(strWhere), strWhere).ToPageList(intPageIndex, intPageSize));
        }


        public async Task<List<TEntity>> QueryPage(Expression<Func<TEntity, bool>> whereExpression,
        int intPageIndex = 0, int intPageSize = 20, string strOrderByFileds = null)
        {
            return await Task.Run(() => db.Queryable<TEntity>()
            .OrderByIF(!string.IsNullOrEmpty(strOrderByFileds), strOrderByFileds)
            .WhereIF(whereExpression != null, whereExpression)
            .ToPageList(intPageIndex, intPageSize));
        }

        public Task<int> AddAsync(TEntity model)
        {
            throw new NotImplementedException();
        }
    }
}

然後呢,同樣在在Blog.Core.Repository 層中,將其他的接口,繼承BaseRepository,這裏略過,按下不表。

image

這裏要說下,昨天有人問我DbContext.cs內容講一下,其實呢,這個類裏,很簡單,主要是1、獲取SqlSugarClient實例,2、CodeFirst(根據實體類生成數據庫表);3、DbFirst(根據數據庫表生成實體類)。只不過都是用到的同名方法重載,可能看上去比較累,可以調用一次就能明白了。

這裏簡單說下DbFirst吧,其他的可以自行研究下 DbFirst是一個根據數據庫表生成實體類的過程,前提是要有系統表的權限,否則無法讀取表的結構,框架在底層封裝了很多模板,將真實值填充進去,特別像是動軟代碼生成器或者T4模板。

四、設計應用服務層基類與基接口

同樣在Blog.Core.IServices 和 Blog.Core.Services 層中,分別添加基接口,並實現基類
IBaseServices.cs

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

namespace Blog.Core.IServices.Base
{
    public interface IBaseServices<TEntity> where TEntity : class
    {
        Task<TEntity> QueryByID(object objId);
        Task<TEntity> QueryByID(object objId,bool blnUseCache = false);
        Task<int> Add(TEntity entity);
        Task<bool> DeleteById(object id);
        Task<bool> Delete(TEntity model);
        Task<bool> DeleteByIds(object[] ids);
        Task<bool> Update(TEntity model);
        Task<bool> Update(TEntity entity, string strWhere);
        Task<bool> Update(TEntity entity, List<string> lstColumns = null, List<string> lstIgnoreColumns = null, string strWhere = "");
        Task<List<TEntity>> Query();
        Task<List<TEntity>> Query(string strWhere);
        Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression);
        Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, string strOrderByFileds);
        Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, object>> orderByExpression, bool isAsc = true);
        Task<List<TEntity>> Query(string strWhere, string strOrderByFileds);
        Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, int intTop, string strOrderByFileds);
        Task<List<TEntity>> Query(string strWhere, int intTop, string strOrderByFileds);
        Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, int intPageIndex, int intPageSize, string strOrderByFileds);
        Task<List<TEntity>> Query(string strWhere, int intPageIndex, int intPageSize, string strOrderByFileds);
        Task<List<TEntity>> QueryPage(Expression<Func<TEntity, bool>> whereExpression, int intPageIndex = 0, int intPageSize = 20, string strOrderByFileds = null);
    }
}

BaseServices.cs

using Blog.Core.IRepository.Base;
using Blog.Core.IServices.Base;
using Blog.Core.Repository.Base;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Blog.Core.Services.Base
{
    public class BaseServices<TEntity> : IBaseServices<TEntity> where TEntity : class, new()
    {
        public IBaseRepository<TEntity> baseDal = new BaseRepository<TEntity>();

        public async Task<int> Add(TEntity entity)
        {
            return await baseDal.AddAsync(entity);
        }

        public async Task<bool> Delete(TEntity model)
        {
            return await baseDal.Delete(model);
        }

        public async Task<bool> DeleteById(object id)
        {
            return await baseDal.DeleteById(id);
        }

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

        public async Task<List<TEntity>> Query()
        {
            return await baseDal.Query();
        }

        public async Task<List<TEntity>> Query(string strWhere)
        {
            return await baseDal.Query(strWhere);
        }

        public async Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression)
        {
            return await baseDal.Query(whereExpression);
        }

        public async Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, string strOrderByFileds)
        {
            return await baseDal.Query(whereExpression, strOrderByFileds);
        }

        public async Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, object>> orderByExpression, bool isAsc = true)
        {
            return await baseDal.Query(whereExpression, orderByExpression,isAsc);
        }

        public async Task<List<TEntity>> Query(string strWhere, string strOrderByFileds)
        {
            return await baseDal.Query(strWhere, strOrderByFileds);
        }

        public async Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, int intTop, string strOrderByFileds)
        {
            return await baseDal.Query(whereExpression, intTop, strOrderByFileds);
        }

        public async Task<List<TEntity>> Query(string strWhere, int intTop, string strOrderByFileds)
        {
            return await baseDal.Query(strWhere, intTop, strOrderByFileds);
        }

        public async Task<List<TEntity>> Query(Expression<Func<TEntity, bool>> whereExpression, int intPageIndex, int intPageSize, string strOrderByFileds)
        {
            return await baseDal.Query(whereExpression, intPageIndex, intPageSize, strOrderByFileds);
        }

        public async Task<List<TEntity>> Query(string strWhere, int intPageIndex, int intPageSize, string strOrderByFileds)
        {
            return await baseDal.Query(strWhere, intPageIndex, intPageSize, strOrderByFileds);
        }

        public async Task<TEntity> QueryByID(object objId)
        {
            return await baseDal.QueryByID(objId);
        }

        public async Task<TEntity> QueryByID(object objId, bool blnUseCache = false)
        {
            return await baseDal.QueryByID(objId, blnUseCache);
        }

        public async Task<List<TEntity>> QueryPage(Expression<Func<TEntity, bool>> whereExpression, int intPageIndex = 0, int intPageSize = 20, string strOrderByFileds = null)
        {
            return await baseDal.QueryPage(whereExpression, intPageIndex, intPageSize, strOrderByFileds);
        }

        public async Task<bool> Update(TEntity model)
        {
            return await baseDal.Update(model);
        }

        public async Task<bool> Update(TEntity entity, string strWhere)
        {
            return await baseDal.Update(entity,strWhere);
        }

        public Task<bool> Update(TEntity entity, List<string> lstColumns = null, List<string> lstIgnoreColumns = null, string strWhere = "")
        {
            return baseDal.Update(entity,lstColumns, lstIgnoreColumns, strWhere);
        }
    }
}

五、運行項目,並調試接口

這個時候,需要把接口改成異步請求方式:

        [HttpGet("{id}", Name = "Get")]
        public async Task<List<Advertisement>> GetAsync(int id)
        {
            IAdvertisementServices service = new AdvertisementServices();
            return await service.Get(id);
        }

Http返回200,一切正常。

image

六、初探依賴注入

首先,我們需要了解下什麼是控制反轉IOC,舉個栗子,我在之前開發簡單商城的時候,其中呢,訂單模塊,有訂單表,那裏邊肯定有訂單詳情表,而且呢訂單詳情表中還有商品信息表,商品信息表還關聯了價格規格表,或者其他的物流信息,商家信息,當然,我們可以放到一個大表裏,可是你一定不會這麼做,因爲太龐大,所以必定分表,那必定會出現類中套類的局面,這就是依賴,比如上邊的,訂單表就依賴了詳情表,我們在實例化訂單實體類的時候,也需要手動實例詳情表,當然,EF框架中,會自動生成。不過倘若有一個程序員把詳情表實體類改錯了,那訂單表就崩潰了,哦不!我是遇到過這樣的情景。

image

怎麼解決這個問題呢,就出現了控制反轉。網上看到一個挺好的講解:

1、沒有引入IOC之前,對象A依賴於對象B,那麼對象A在初始化或者運行到某一點的時候,A直接使用new關鍵字創建B的實例,程序高度耦合,效率低下,無論是創建還是使用B對象,控制權都在自己手上。

2、軟件系統在引入IOC容器之後,這種情形就完全改變了,由於IOC容器的加入,對象A與對象B之間失去了直接聯繫,所以,當對象A運行到需要對象B的時候,IOC容器會主動創建一個對象B注入到對象A需要的地方。

3、依賴注入,是指程序運行過程中,如果需要調用另一個對象協助時,無須在代碼中創建被調用者,而是依賴於外部的注入。Spring的依賴注入對調用者和被調用者幾乎沒有任何要求,完全支持對POJO之間依賴關係的管理。依賴注入通常有兩種:
·設值注入。
·構造注入。

這個就是依賴注入的方式。

什麼是控制反轉(IoC)


Inversion of Control,英文縮寫爲IoC,不是什麼技術,而是一種設計思想。

 

簡單來說就是把複雜系統分解成相互合作的對象,這些對象類通過封裝以後,內部實現對外部是透明的,從而降低了解決問題的複雜度,而且可以靈活地被重用和擴展。IOC理論提出的觀點大體是這樣的:藉助於“第三方”實現具有依賴關係的對象之間的解耦,如下圖:

image

大家看到了吧,由於引進了中間位置的“第三方”,也就是IOC容器,使得A、B、C、D這4個對象沒有了耦合關係,齒輪之間的傳動全部依靠“第三方”了,全部對象的控制權全部上繳給“第三方”IOC容器,所以,IOC容器成了整個系統的關鍵核心,它起到了一種類似“黏合劑”的作用,把系統中的所有對象粘合在一起發揮作用,如果沒有這個“黏合劑”,對象與對象之間會彼此失去聯繫,這就是有人把IOC容器比喻成“黏合劑”的由來。

 

我們再來做個試驗:把上圖中間的IOC容器拿掉,然後再來看看這套系統:

image

 

我們現在看到的畫面,就是我們要實現整個系統所需要完成的全部內容。這時候,A、B、C、D這4個對象之間已經沒有了耦合關係,彼此毫無聯繫,這樣的話,當你在實現A的時候,根本無須再去考慮B、C和D了,對象之間的依賴關係已經降低到了最低程度。所以,如果真能實現IOC容器,對於系統開發而言,這將是一件多麼美好的事情,參與開發的每一成員只要實現自己的類就可以了,跟別人沒有任何關係!

因爲時間和篇幅的關係,今天在項目中,暫時不引入Autofac了,下週我們繼續深入瞭解。

七、結語

寫文章原來也是一個體力活,嗯加油!今天終於將後端框架補充了下,實現了基本的功能,重點講解了如何在倉儲模式中,使用基類泛型,當然這是一個思想,你也可以在開發的過程中,多使用抽象類,接口編程;

然後呢,又簡單的使用了異步編程,現在也是很流行的一直寫法,我也是剛使用,大家歡迎批評指正;

簡單的瞭解了下,IOC控制反轉和DI依賴注入,爲下次做準備;

當然,現在才僅僅是一個雛形,以後還會用到AOP的日誌,異常記錄;Redis的緩存等,慢慢來吧,給自己加加油!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章