從壹開始前后端分離【 .NET Core2.0 Api + Vue 2.0 + AOP + 分布式】框架之七 || API項(xiàng)目整體搭建 6.2 輕量級(jí)ORM

代碼已上傳Github,文末有地址

書接上文:《從壹開始前后端分離【 .NET Core2.0 Api + Vue 2.0 + AOP + 分布式】框架之六 || API項(xiàng)目整體搭建 6.1 倉儲(chǔ)》,我們簡(jiǎn)單的對(duì)整體項(xiàng)目進(jìn)行搭建,用到了項(xiàng)目中常見的倉儲(chǔ)模式+面向接口編程,核心的一共是六層,當(dāng)然你也可以根據(jù)自己的需求進(jìn)行擴(kuò)展,比如我在其他的項(xiàng)目中會(huì)用到Common層,當(dāng)然我們這個(gè)項(xiàng)目接下來也會(huì)有,或者我還會(huì)添加Task層,主要是作為定時(shí)項(xiàng)目使用,我之前用的是Task Schedule,基本能滿足需求。

緣起

在上一節(jié)中,我們最后提出了兩個(gè)問題,不知道大家是否還記得,這里還重新說明一下:

1、如果每個(gè)倉儲(chǔ)文件都需要把一個(gè)一個(gè)寫出來,至少是四遍,會(huì)不會(huì)太麻煩,而且無法復(fù)用,失去了面向接口編程的意義;

2、每次接口調(diào)用的時(shí)候,需要引入很多命名空間,比如Blog.Core.IServices;Blog.Core.Services;Blog.Core.Repository等等

對(duì)就是這兩個(gè)問題,相信聰明的大家也都能看懂,或許還能給出相應(yīng)的解決辦法,比如泛型倉儲(chǔ),比如依賴注入,當(dāng)然,如果你有更好的辦法,歡迎留言,我會(huì)把你的想法寫下了,讓大家一起進(jìn)步。這里先簡(jiǎn)單說下問題1中為什么要四遍,倉儲(chǔ)模式的基本就是如何將持久化動(dòng)作和對(duì)象獲取方式以及領(lǐng)域模型Domain Model結(jié)合起來,進(jìn)一步:如何更加統(tǒng)一我們的語言(Ubiquitous Language),一個(gè)整合持久化技術(shù)的好辦法是倉儲(chǔ)Repositories。明白了這個(gè)問題,你就知道,定義倉儲(chǔ),首先需要定義IRepository接口(1),然后再Repository中實(shí)現(xiàn)(2),接著在IService層中引用這些接口,同時(shí)也可以自定義擴(kuò)展業(yè)務(wù)邏輯接口(3),最后在Service層中去實(shí)現(xiàn)(4),這就是四層。

問題明白了,我們就要?jiǎng)邮肿銎饋?,思考了下,如果干巴巴直接寫泛型倉儲(chǔ),會(huì)比較干澀,所以我考慮今天先把數(shù)據(jù)持久化做出來,一個(gè)輕量級(jí)的ORM框架——SqlSugar。

零、今天完成的藍(lán)色部分

image

一、在Blog.Core.IRepository 層中添加CURD接口

還記得昨天我們實(shí)現(xiàn)的Sum接口么,今天在倉儲(chǔ)接口 IAdvertisementRepository.cs 添加CURD四個(gè)接口,首先需要將Model層添加引用,這個(gè)應(yīng)該都會(huì),以后不再細(xì)說,如下:

image
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);

    }
}

編譯項(xiàng)目,提示錯(cuò)誤,別慌!很正常,因?yàn)槲覀儸F(xiàn)在只是添加了接口,還沒有實(shí)現(xiàn)接口。

二、在Blog.Core.Repository 層中實(shí)現(xiàn)Blog.Core.IRepository 所定義的CURD接口

當(dāng)然,我們還是在AdvertisementRepository.cs文件中操作,這里我有一個(gè)小技巧,不知道大家是否用到過,因?yàn)槲冶容^喜歡寫接口,這樣不僅可以不暴露核心代碼,而且也可以讓用戶調(diào)用的時(shí)候,直接看到簡(jiǎn)單的接口方法列表,而不去管具體的實(shí)現(xiàn)過程,這樣的設(shè)計(jì)思路還是比較提倡的,如下圖:

image

你先看到了繼承的接口有紅色的波浪線,證明有錯(cuò)誤,然后右鍵該接口,點(diǎn)擊 Quick Actions and Refactorings...,也就是 快速操作和重構(gòu) ,你就會(huì)看到VS的智能提示,雙擊左側(cè)的Implement interface,也就是實(shí)現(xiàn)接口,如下圖:

image

Visual Studio真是宇宙第一IDE,沒的說 [手動(dòng)點(diǎn)贊],然后就創(chuàng)建成功了,你就可以去掉throw處理,自定義代碼編寫了,當(dāng)然,如果你不習(xí)慣或者害怕出錯(cuò),那就手動(dòng)寫吧,也是很快的。

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();
        }
    }
}

這個(gè)時(shí)候我們重新編譯項(xiàng)目,嗯!意料之中,沒有錯(cuò)誤,但是具體的數(shù)據(jù)持久化如何寫呢?

三、引用輕量級(jí)的ORM框架——SqlSugar

首先什么是ORM, 對(duì)象關(guān)系映射(Object Relational Mapping,簡(jiǎn)稱ORM)模式是一種為了解決面向?qū)ο笈c關(guān)系數(shù)據(jù)庫存在的互不匹配的現(xiàn)象的技術(shù)。簡(jiǎn)單的說,ORM是通過使用描述對(duì)象和數(shù)據(jù)庫之間映射的元數(shù)據(jù),將程序中的對(duì)象自動(dòng)持久化到關(guān)系數(shù)據(jù)庫中。這些概念我就不細(xì)說了,自從開發(fā)這些年,一直在討論的問題就是用ADO.NET還是用ORM框架,還記得前幾年面試的時(shí)候,有一個(gè)經(jīng)理問:

如果一個(gè)項(xiàng)目,你是用三層架構(gòu)ADO,還是用ORM中的EF?

大家可以自由留言,我表示各有千秋吧,一個(gè)產(chǎn)品的存在即有合理性,我平時(shí)項(xiàng)目中也有ADO,也有EF,不過本系列教程中基于面向?qū)ο笏枷?,面向接口思想,?dāng)然還有以后的面向切面編程(AOP),還是使用ORM框架,不過是一個(gè)輕量級(jí)的,EF比較重,我在我其他的項(xiàng)目中用到了.Net MVC 6.0 + EF Code First 的項(xiàng)目,如果大家需要,我也開源出去,方法Github上,請(qǐng)文末留言吧~

關(guān)于ORM有一些常見的框架,如SqlSugar、Dapper、EF、NHeberneit等等,這些我都或多或少的了解過,使用過,至于你要問我為啥用SqlSugar,只要一個(gè)原因,作者是中國人,嗯!沒錯(cuò),這里給他打個(gè)廣告,本系列中的前端框架Vue,也是我們中國的,Vue作者尤雨溪,這里也祝福大家都能有自己的成績(jī),為國人爭(zhēng)光!

image

扯遠(yuǎn)了,開始動(dòng)手引入框架:

開始,我們需要先向 Repository 層中引入SqlSugar,如下:

1)直接在類庫中通過Nuget引入 sqlSugarCore,一定是Core版本的!,我個(gè)人采用這個(gè)辦法,因?yàn)轫?xiàng)目已經(jīng)比較成型

2)Github下載源碼,然后項(xiàng)目引用(點(diǎn)擊跳轉(zhuǎn)到Github下載頁)

注意:為什么要單獨(dú)在倉儲(chǔ)層來引入ORM持久化接口,是因?yàn)椋档婉詈?,如果以后想要換成EF或者Deper,只需要修改Repository就行了,其他都不需要修改,達(dá)到很好的解耦效果。

image

編譯一切正常,繼續(xù)

首先呢,你需要了解下sqlsugar的具體使用方法,http://www.codeisbug.com/Doc/8,你先自己在控制臺(tái)可以簡(jiǎn)單試一試,這里就不細(xì)說了,如果大家有需要,我可以單開一個(gè)文章,重點(diǎn)講解SqlSugar這一塊。

1、在Blog.Core.Repository新建一個(gè)sugar文件夾,然后添加兩個(gè)配置文件,BaseDBConfig.cs 和 DbContext.cs ,這個(gè)你如果看了上邊的文檔,那這兩個(gè)應(yīng)該就不是問題。

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"; 

        //原諒我用配置文件的形式,因?yàn)槲抑苯诱{(diào)用的是我的服務(wù)器賬號(hào)和密碼,安全起見

    }
}

//DbContext.cs,一個(gè)詳細(xì)的上下文類,看不懂沒關(guān)系,以后我會(huì)詳細(xì)講解

    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>
        /// 數(shù)據(jù)庫類型 
        /// Blog.Core 
        /// </summary>
        public static DbType DbType
        {
            get { return _dbType; }
            set { _dbType = value; }
        }
        /// <summary>
        /// 數(shù)據(jù)連接對(duì)象 
        /// Blog.Core 
        /// </summary>
        public SqlSugarClient Db
        {
            get { return _db; }
            private set { _db = value; }
        }

        /// <summary>
        /// 數(shù)據(jù)庫上下文實(shí)例(自動(dòng)關(guān)閉連接)
        /// Blog.Core 
        /// </summary>
        public static DbContext Context
        {
            get
            {
                return new DbContext();
            }

        }


        /// <summary>
        /// 功能描述:構(gòu)造函數(shù)
        /// 作  者:Blog.Core
        /// </summary>
        private DbContext()
        {
            if (string.IsNullOrEmpty(_connectionString))
                throw new ArgumentNullException("數(shù)據(jù)庫連接字符串為空");
            _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>
        /// 功能描述:構(gòu)造函數(shù)
        /// 作  者:Blog.Core
        /// </summary>
        /// <param name="blnIsAutoCloseConnection">是否自動(dòng)關(guān)閉連接</param>
        private DbContext(bool blnIsAutoCloseConnection)
        {
            if (string.IsNullOrEmpty(_connectionString))
                throw new ArgumentNullException("數(shù)據(jù)庫連接字符串為空");
            _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 實(shí)例方法
        /// <summary>
        /// 功能描述:獲取數(shù)據(jù)庫處理對(duì)象
        /// 作  者:Blog.Core
        /// </summary>
        /// <returns>返回值</returns>
        public SimpleClient<T> GetEntityDB<T>() where T : class, new()
        {
            return new SimpleClient<T>(_db);
        }
        /// <summary>
        /// 功能描述:獲取數(shù)據(jù)庫處理對(duì)象
        /// 作  者: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 根據(jù)數(shù)據(jù)庫表生產(chǎn)實(shí)體類
        /// <summary>
        /// 功能描述:根據(jù)數(shù)據(jù)庫表生產(chǎn)實(shí)體類
        /// 作  者:Blog.Core
        /// </summary>       
        /// <param name="strPath">實(shí)體類存放路徑</param>
        public void CreateClassFileByDBTalbe(string strPath)
        {
            CreateClassFileByDBTalbe(strPath, "Km.PosZC");
        }
        /// <summary>
        /// 功能描述:根據(jù)數(shù)據(jù)庫表生產(chǎn)實(shí)體類
        /// 作  者:Blog.Core
        /// </summary>
        /// <param name="strPath">實(shí)體類存放路徑</param>
        /// <param name="strNameSpace">命名空間</param>
        public void CreateClassFileByDBTalbe(string strPath, string strNameSpace)
        {
            CreateClassFileByDBTalbe(strPath, strNameSpace, null);
        }

        /// <summary>
        /// 功能描述:根據(jù)數(shù)據(jù)庫表生產(chǎn)實(shí)體類
        /// 作  者:Blog.Core
        /// </summary>
        /// <param name="strPath">實(shí)體類存放路徑</param>
        /// <param name="strNameSpace">命名空間</param>
        /// <param name="lstTableNames">生產(chǎn)指定的表</param>
        public void CreateClassFileByDBTalbe(
            string strPath,
            string strNameSpace,
            string[] lstTableNames)
        {
            CreateClassFileByDBTalbe(strPath, strNameSpace, lstTableNames, string.Empty);
        }

        /// <summary>
        /// 功能描述:根據(jù)數(shù)據(jù)庫表生產(chǎn)實(shí)體類
        /// 作  者:Blog.Core
        /// </summary>
        /// <param name="strPath">實(shí)體類存放路徑</param>
        /// <param name="strNameSpace">命名空間</param>
        /// <param name="lstTableNames">生產(chǎn)指定的表</param>
        /// <param name="strInterface">實(shí)現(xiàn)接口</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 根據(jù)實(shí)體類生成數(shù)據(jù)庫表
        /// <summary>
        /// 功能描述:根據(jù)實(shí)體類生成數(shù)據(jù)庫表
        /// 作  者:Blog.Core
        /// </summary>
        /// <param name="blnBackupTable">是否備份表</param>
        /// <param name="lstEntitys">指定的實(shí)體</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>
        /// 功能描述:根據(jù)實(shí)體類生成數(shù)據(jù)庫表
        /// 作  者:Blog.Core
        /// </summary>
        /// <param name="blnBackupTable">是否備份表</param>
        /// <param name="lstEntitys">指定的實(shí)體</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 靜態(tài)方法

        /// <summary>
        /// 功能描述:獲得一個(gè)DbContext
        /// 作  者:Blog.Core
        /// </summary>
        /// <param name="blnIsAutoCloseConnection">是否自動(dòng)關(guān)閉連接(如果為false,則使用接受時(shí)需要手動(dòng)關(guān)閉Db)</param>
        /// <returns>返回值</returns>
        public static DbContext GetDbContext(bool blnIsAutoCloseConnection = true)
        {
            return new DbContext(blnIsAutoCloseConnection);
        }

        /// <summary>
        /// 功能描述:設(shè)置初始化參數(shù)
        /// 作  者:Blog.Core
        /// </summary>
        /// <param name="strConnectionString">連接字符串</param>
        /// <param name="enmDbType">數(shù)據(jù)庫類型</param>
        public static void Init(string strConnectionString, DbType enmDbType = SqlSugar.DbType.SqlServer)
        {
            _connectionString = strConnectionString;
            _dbType = enmDbType;
        }

        /// <summary>
        /// 功能描述:創(chuàng)建一個(gè)鏈接配置
        /// 作  者:Blog.Core
        /// </summary>
        /// <param name="blnIsAutoCloseConnection">是否自動(dòng)關(guān)閉連接</param>
        /// <param name="blnIsShardSameThread">是否夸類事務(wù)</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>
        /// 功能描述:獲取一個(gè)自定義的DB
        /// 作  者:Blog.Core
        /// </summary>
        /// <param name="config">config</param>
        /// <returns>返回值</returns>
        public static SqlSugarClient GetCustomDB(ConnectionConfig config)
        {
            return new SqlSugarClient(config);
        }
        /// <summary>
        /// 功能描述:獲取一個(gè)自定義的數(shù)據(jù)庫處理對(duì)象
        /// 作  者: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>
        /// 功能描述:獲取一個(gè)自定義的數(shù)據(jù)庫處理對(duì)象
        /// 作  者: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
    }

image

2、然后在剛剛我們實(shí)現(xiàn)那四個(gè)方法的AdvertisementRepository.cs中,重寫構(gòu)造函數(shù),編輯統(tǒng)一Sqlsugar實(shí)例方法,用到了私有屬性,為以后的單列模式做準(zhǔn)備。

  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層中,添加了全局的數(shù)據(jù)類型轉(zhuǎn)換方法,UtilConvert,這樣就不用每次都Convert,而且也解決了為空轉(zhuǎn)換異常的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;
        }
    }

最終的倉儲(chǔ)持久化是:

namespace Blog.Core.Repository
{
    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類型,這里你可以根據(jù)你的業(yè)務(wù)需要進(jìn)行處理
            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)
        {
            //這種方式會(huì)以主鍵為條件
            var i =   db.Updateable(model).ExecuteCommand();
            return i > 0;
        }
    }
}

四、在 Blog.Core.IServices 層設(shè)計(jì)CURD接口,和倉儲(chǔ)接口一樣,在Blog.Core.Services去實(shí)現(xiàn)

這里不細(xì)說,記得添加引用,最終的代碼是:

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);
        }

    }
}

都是很簡(jiǎn)單,如果昨天的Sum方法你會(huì)了,這個(gè)肯定都會(huì)。

五、Controller測(cè)試接口,數(shù)據(jù)庫Sql生成語句在wwwroot文件中

實(shí)現(xiàn)工作,根據(jù)id獲取數(shù)據(jù)

這里為了調(diào)試方便,我把權(quán)限驗(yàn)證暫時(shí)注釋掉

//[Authorize(Policy ="Admin")]

image

然后修改我們的其中一個(gè)Get方法,根據(jù)id獲取信息

  // GET: api/Blog/5
        /// <summary>
        /// 根據(jù)id獲取數(shù)據(jù)
        /// </summary>
        /// <param name="id">參數(shù)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);
        }

接下來運(yùn)行調(diào)試,在我們接口文檔中,直接點(diǎn)擊調(diào)試

image

得到的結(jié)果是如果,雖然是空的,但是返回結(jié)果http代碼是200,因?yàn)楸碇袥]數(shù)據(jù)嘛

image

六、結(jié)語

好啦,今天的講解就到這里,你簡(jiǎn)單的了解了什么是ORM,以及其中的SqlSugar,然后呢,倉儲(chǔ)模式的具體使用,最后還有真正的連接數(shù)據(jù)庫,獲取到數(shù)據(jù),下一節(jié)中,我們繼續(xù)來解決兩大問題,來實(shí)現(xiàn)泛型倉儲(chǔ)。

七、CODE

https://github.com/anjoy8/Blog.Core.git
QQ群:

867095512 (blod.core)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容