.Net Core2.0下使用Dapper遇到的问题
今天成功把.Net Framework下使用Dapper進(jìn)行封裝的ORM成功遷移到.Net Core 2.0上,在遷移的過程中也遇到一些很有意思的問題,值得和大家分享一下。下面我會(huì)還原遷移的每一個(gè)過程,以及在此過程中遇到的問題和處理這些問題的方法。
一、遷移前的準(zhǔn)備
之前對(duì)Dapper的封裝使用的是.Net Framework下的ORM 框架Dapper,開發(fā)工具VS2013,現(xiàn)在既然想在.Net Core2.0上使用Dapper,我要先到NuGet看看有沒有支持 .Net Core的,在Nuget找到如下:
果然有!!!因?yàn)轫?xiàng)目中使用的是MySQL,所以還要看看有沒有MySQL的.Net驅(qū)動(dòng),發(fā)現(xiàn)也有,但是是預(yù)發(fā)行版本,算了等不及正式版了,先用(生產(chǎn)環(huán)境中我暫時(shí)沒使用)它來(lái)測(cè)試,等正式版出來(lái)就正式遷移了(* ̄︶ ̄)
好了,該準(zhǔn)備的已經(jīng)準(zhǔn)備好了,下面就是使用VS2017新建一個(gè)項(xiàng)目,用來(lái)測(cè)試,項(xiàng)目的整體結(jié)構(gòu)如下:
二、正式遷移
.Net Framework下對(duì)Dapper進(jìn)行的二次封裝,代碼部分如下,后面會(huì)介紹我為什么要這樣封裝:?
namespace ZSZ.Core.Respository
{
? ? public interface IDataAdapter
? ? {
? ? ? ? string BindVariablePrefix { get; }
? ? ? ? void AppendColumnName(StringBuilder sb, string columnName);
? ? ? ? void AppendColumnNameEqualsValue(StringBuilder sb, string columnName);
? ? ? ? void AppendUpdateColumnName(StringBuilder sb, string columnName);
? ? }
? ? public class OracleDataAdapter : IDataAdapter
? ? {
? ? ? ? public string BindVariablePrefix
? ? ? ? {
? ? ? ? ? ? get { return ":"; }
? ? ? ? }
? ? ? ? public void AppendColumnName(StringBuilder sb, string columnName)
? ? ? ? {
? ? ? ? ? ? sb.AppendFormat("{0}, ", columnName.ToUpper());
? ? ? ? }
? ? ? ? public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
? ? ? ? {
? ? ? ? ? ? sb.AppendFormat("{0}{1}, ", BindVariablePrefix, columnName.ToUpper());
? ? ? ? }
? ? ? ? public void AppendUpdateColumnName(StringBuilder sb, string columnName)
? ? ? ? {
? ? ? ? ? ? sb.AppendFormat("{0}={1}{0}, ", columnName.ToUpper(), BindVariablePrefix);
? ? ? ? }
? ? }
? ? public class SqlServerDataAdapter : IDataAdapter
? ? {
? ? ? ? public string BindVariablePrefix
? ? ? ? {
? ? ? ? ? ? get { return "@"; }
? ? ? ? }
? ? ? ? public void AppendColumnName(StringBuilder sb, string columnName)
? ? ? ? {
? ? ? ? ? ? sb.AppendFormat("{0}, ", columnName.ToUpper());
? ? ? ? }
? ? ? ? public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
? ? ? ? {
? ? ? ? ? ? sb.AppendFormat("{0}{1}, ", BindVariablePrefix, columnName.ToUpper());
? ? ? ? }
? ? ? ? public void AppendUpdateColumnName(StringBuilder sb, string columnName)
? ? ? ? {
? ? ? ? ? ? sb.AppendFormat("{0}={1}{0}, ", columnName.ToUpper(), BindVariablePrefix);
? ? ? ? }
? ? }
? ? public class MySqlDataAdapter : IDataAdapter
? ? {
? ? ? ? public string BindVariablePrefix
? ? ? ? {
? ? ? ? ? ? get { return "@"; }
? ? ? ? }
? ? ? ? public void AppendColumnName(StringBuilder sb, string columnName)
? ? ? ? {
? ? ? ? ? ? sb.AppendFormat("{0}, ", columnName.ToUpper());
? ? ? ? }
? ? ? ? public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
? ? ? ? {
? ? ? ? ? ? sb.AppendFormat("{0}{1}, ", BindVariablePrefix, columnName.ToUpper());
? ? ? ? }
? ? ? ? public void AppendUpdateColumnName(StringBuilder sb, string columnName)
? ? ? ? {
? ? ? ? ? ? sb.AppendFormat("{0}={1}{0}, ", columnName.ToUpper(), BindVariablePrefix);
? ? ? ? }
? ? }
? ? public static class DataBase
? ? {
? ? ? ? internal class TypeInsertPair
? ? ? ? {
? ? ? ? ? ? public string Columns { get; set; }
? ? ? ? ? ? public string Values { get; set; }
? ? ? ? }
? ? ? ? /*
? ? ? ? ?*?
? ? ? ? ?*?
? ? ? ? ?* 線程安全:如果你的代碼所在的進(jìn)程中有多個(gè)線程在同時(shí)運(yùn)行,而這些線程可能會(huì)同時(shí)運(yùn)行這段代碼。如果每次運(yùn)行結(jié)果和單線程運(yùn)行的結(jié)果是一樣的,而且其他的變量的值也和預(yù)期的是一樣的,就是線程安全的。
? ? ? ? ?* http://www.cnblogs.com/CreateMyself/p/6086752.html
? ? ? ? ?* http://www.cnblogs.com/PurpleTide/archive/2011/11/21/2256577.html
? ? ? ? ?* http://www.cnblogs.com/lori/p/4344026.html
? ? ? ? ?*/
? ? ? ? private static readonly ConcurrentDictionary<RuntimeTypeHandle, TypeInsertPair> TypeInsertPairDictionary = new ConcurrentDictionary<RuntimeTypeHandle, TypeInsertPair>();
? ? ? ? private static readonly ConcurrentDictionary<RuntimeTypeHandle, string> TypeUpdateDictionary = new ConcurrentDictionary<RuntimeTypeHandle, string>();
? ? ? ? private static readonly ConcurrentDictionary<RuntimeTypeHandle, string> TypeColumnsDictionary = new ConcurrentDictionary<RuntimeTypeHandle, string>();
? ? ? ? private static IDataAdapter defaultDataAdapter;
? ? ? ? private static IDataAdapter DefaultDataAdapter
? ? ? ? {
? ? ? ? ? ? get
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if (defaultDataAdapter == null)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? defaultDataAdapter = GetDataAdapter(DefaultConnectionStringSettings);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? return defaultDataAdapter;
? ? ? ? ? ? }
? ? ? ? ? ? set
? ? ? ? ? ? {
? ? ? ? ? ? ? ? defaultDataAdapter = value;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? public static IDataAdapter GetDataAdapter(this ConnectionStringSettings connectionStringSettings)
? ? ? ? {
? ? ? ? ? ? if (connectionStringSettings == null)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? return defaultDataAdapter;
? ? ? ? ? ? }
? ? ? ? ? ? if (string.IsNullOrEmpty(connectionStringSettings.ProviderName))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? throw new Exception("數(shù)據(jù)庫(kù)連接串的配置不正確!");
? ? ? ? ? ? }
? ? ? ? ? ? if (connectionStringSettings.ProviderName.ToLower().Contains("oracle"))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? return new OracleDataAdapter();
? ? ? ? ? ? }
? ? ? ? ? ? else if (connectionStringSettings.ProviderName.ToLower().Contains("mysql"))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? return new MySqlDataAdapter();
? ? ? ? ? ? }
? ? ? ? ? ? else if (connectionStringSettings.ProviderName.ToLower().Contains("sql"))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? return new SqlServerDataAdapter();
? ? ? ? ? ? }
? ? ? ? ? ? throw new Exception("暫不支持您使用的數(shù)據(jù)庫(kù)類型!");
? ? ? ? }
? ? ? ? private static ConnectionStringSettings defaultConnectionStringSettings;
? ? ? ? public static ConnectionStringSettings DefaultConnectionStringSettings
? ? ? ? {
? ? ? ? ? ? get
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if (defaultConnectionStringSettings == null)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? defaultConnectionStringSettings = ConfigurationManager.ConnectionStrings["db"];
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? return defaultConnectionStringSettings;
? ? ? ? ? ? }
? ? ? ? ? ? set
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if (value == null) throw new Exception("默認(rèn)的數(shù)據(jù)庫(kù)連接配置信息不能為空!");
? ? ? ? ? ? ? ? defaultConnectionStringSettings = value;
? ? ? ? ? ? ? ? DefaultDataAdapter = GetDataAdapter(value);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? private static IDbConnection GetDbConnection(this ConnectionStringSettings connectionStringSettings)
? ? ? ? {
? ? ? ? ? ? if (connectionStringSettings != null && (string.IsNullOrEmpty(connectionStringSettings.ConnectionString) || string.IsNullOrEmpty(connectionStringSettings.ProviderName))) throw new Exception("數(shù)據(jù)庫(kù)鏈接字符串配置不正確!");
? ? ? ? ? ? var settings = connectionStringSettings == null ? DefaultConnectionStringSettings : connectionStringSettings;
? ? ? ? ? ? var factory = System.Data.Common.DbProviderFactories.GetFactory(settings.ProviderName);
? ? ? ? ? ? var connection = factory.CreateConnection();
? ? ? ? ? ? connection.ConnectionString = settings.ConnectionString;
? ? ? ? ? ? return connection;
? ? ? ? }
? ? ? ? private static TypeInsertPair GetTypeInsertPair(this Type type, IDataAdapter adapter)
? ? ? ? {
? ? ? ? ? ? if (TypeInsertPairDictionary.ContainsKey(type.TypeHandle)) return TypeInsertPairDictionary[type.TypeHandle];
? ? ? ? ? ? var columns = new StringBuilder();
? ? ? ? ? ? var values = new StringBuilder();
? ? ? ? ? ? foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if (property.IsIgnore() && !"id".Equals(property.Name, StringComparison.OrdinalIgnoreCase)) continue;
? ? ? ? ? ? ? ? adapter.AppendColumnName(columns, property.Name);
? ? ? ? ? ? ? ? adapter.AppendColumnNameEqualsValue(values, property.Name);
? ? ? ? ? ? }
? ? ? ? ? ? var pair = new TypeInsertPair() { Columns = columns.ToString().Substring(0, columns.Length - 2), Values = values.ToString().Substring(0, values.Length - 2) };
? ? ? ? ? ? TypeInsertPairDictionary[type.TypeHandle] = pair;
? ? ? ? ? ? return pair;
? ? ? ? }
? ? ? ? private static string GetTypeColumns(this Type type, ConnectionStringSettings connectionStringSettings)
? ? ? ? {
? ? ? ? ? ? if (TypeColumnsDictionary.ContainsKey(type.TypeHandle)) return TypeColumnsDictionary[type.TypeHandle];
? ? ? ? ? ? var sb = new StringBuilder();
? ? ? ? ? ? var adapter = connectionStringSettings.GetDataAdapter();
? ? ? ? ? ? foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? //查詢時(shí)的字段
? ? ? ? ? ? ? ? adapter.AppendColumnName(sb, property.Name);
? ? ? ? ? ? }
? ? ? ? ? ? var columns = sb.ToString().Substring(0, sb.Length - 2);
? ? ? ? ? ? TypeColumnsDictionary[type.TypeHandle] = columns;
? ? ? ? ? ? return columns;
? ? ? ? }
? ? ? ? private static string GetTypeUpdateSetString(this Type type, ConnectionStringSettings connectionStringSettings)
? ? ? ? {
? ? ? ? ? ? if (TypeUpdateDictionary.ContainsKey(type.TypeHandle)) return TypeUpdateDictionary[type.TypeHandle];
? ? ? ? ? ? var sb = new StringBuilder();
? ? ? ? ? ? var adapter = connectionStringSettings.GetDataAdapter();
? ? ? ? ? ? foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? //更新時(shí)如果傳入實(shí)體對(duì)象的話,會(huì)有ID在里面,所以在這里要把ID(主鍵)去掉
? ? ? ? ? ? ? ? if (property.IsIgnore() || "id".Equals(property.Name, StringComparison.OrdinalIgnoreCase)) continue;
? ? ? ? ? ? ? ? adapter.AppendUpdateColumnName(sb, property.Name);
? ? ? ? ? ? }
? ? ? ? ? ? var update = sb.ToString().Substring(0, sb.Length - 2);
? ? ? ? ? ? TypeUpdateDictionary[type.TypeHandle] = update;
? ? ? ? ? ? return update;
? ? ? ? }
? ? ? ? //如果對(duì)應(yīng)的字段上有這樣的特性就不參與對(duì)應(yīng)的數(shù)據(jù)庫(kù)操作
? ? ? ? private static bool IsIgnore(this PropertyInfo property)
? ? ? ? {
? ? ? ? ? ? var attribute = property.GetCustomAttributes(typeof(IgnoreAttribute), true).FirstOrDefault() as IgnoreAttribute;
? ? ? ? ? ? return attribute != null && attribute.Ignore;
? ? ? ? }
? ? ? ? #region 查詢
? ? ? ? //根據(jù)實(shí)體生成sql,映射返回實(shí)體集合
? ? ? ? //使用:傳過來(lái)condition、param參數(shù)即可
? ? ? ? public static IEnumerable<T> Get<T>(string condition = null, object param = null, string tableName = null, ConnectionStringSettings connectionStringSettings = null, IDbTransaction transaction = null) where T : class
? ? ? ? {
? ? ? ? ? ? if (string.IsNullOrEmpty(tableName) && !(typeof(T).IsSubclassOf(typeof(BaseEntity<T>)))) throw new Exception("沒有輸入表名時(shí)只支持?jǐn)?shù)據(jù)庫(kù)實(shí)體查詢!");
? ? ? ? ? ? var name = string.IsNullOrEmpty(tableName) ? BaseEntity<T>.TableName : tableName;
? ? ? ? ? ? var columns = string.IsNullOrEmpty(tableName) ? "*" : typeof(T).GetTypeColumns(connectionStringSettings);
? ? ? ? ? ? var sql = string.IsNullOrEmpty(condition) ? string.Format("select {0} from {1}", columns, name) : string.Format("select {0} from {1} where {2}", columns, name, condition);
? ? ? ? ? ? var conn = connectionStringSettings.GetDbConnection();
? ? ? ? ? ? return conn.Query<T>(sql, param, transaction);
? ? ? ? }
? ? ? ? //根據(jù)SQL映射實(shí)體或ViewModel
? ? ? ? //使用:傳過來(lái)SQL,讓Dapper進(jìn)行映射
? ? ? ? public static IEnumerable<T> GetBySql<T>(string sql, object param = null, ConnectionStringSettings connectionStringSettings = null, IDbTransaction transaction = null) where T : class
? ? ? ? {
? ? ? ? ? ? var conn = connectionStringSettings.GetDbConnection();
? ? ? ? ? ? return conn.Query<T>(sql, param, transaction);
? ? ? ? }
? ? ? ? //根據(jù)ID獲取單個(gè)實(shí)體對(duì)象
? ? ? ? //使用:傳過來(lái)ID
? ? ? ? public static T GetById<T>(string id, string tableName = null, ConnectionStringSettings connectionStringSettings = null, IDbTransaction transaction = null) where T : class
? ? ? ? {
? ? ? ? ? ? var adapter = connectionStringSettings.GetDataAdapter();
? ? ? ? ? ? return Get<T>(connectionStringSettings: connectionStringSettings, tableName: tableName, condition: string.Format("id ={0}id", adapter.BindVariablePrefix), param: new { id = id }, transaction: transaction).FirstOrDefault();
? ? ? ? }
}
?在把.Net Framework下對(duì)Dapper進(jìn)行二次封裝的代碼放到.Net Core 2.0之前,我們需要在上面新建的項(xiàng)目中引用,如下Nuget包:
(1)
在圖中標(biāo)識(shí)的項(xiàng)目中需要引用Dapper和MySQL
1)Install-Package MySql.Data -Version 8.0.8-dmr
2)Install-Package Dapper -Version 1.50.2
(2)遷移到.Net Core2.0上之后報(bào)錯(cuò)截圖,前提是有些可以手動(dòng)引用,下面列出來(lái)的是ctrl+.還解決不了的。
1)在.Net Framework下 ? ?System.Configuration下有ConnectionStringSettings類,但是在.Net Core中是不是還在同樣的命名空間下?于是查看接口文檔https://docs.microsoft.com/zh-cn/dotnet/api/system.configuration.connectionstringsettings?view=netcore-2.0,發(fā)現(xiàn),真有!!!于是就using System.Configuration;同時(shí)還需要安裝Nuget包: Install-Package System.Configuration.ConfigurationManager,這樣就可以把ConnectionStringSettings類的錯(cuò)誤解決掉。
2)ConfigurationManager類的錯(cuò)誤,關(guān)于讀取配置文件中的信息,可以添加?Microsoft.Extensions.Configuration和Microsoft.Extensions.Configuration.Json來(lái)解決配置文件的讀取問題,還可以使用原始的方式來(lái)讀取,但需要添加 System.Configuration.ConfigurationManager,關(guān)于怎么讀取配置文件中的信息,很簡(jiǎn)單,在這里就不介紹了。下面給一篇關(guān)于如何讀取配置文件信息的文章 :http://www.cnblogs.com/mantgh/p/7425113.html
3)在.Net Framework下, system.Data.Common下有DbProviderFactories類,如下圖:
但是在.Net Core 2.0的接口文檔中沒有找到該類,那該怎么辦?首先在這里講點(diǎn)ADO.Net的相關(guān)知識(shí),我為什么要使用該類?因?yàn)槭褂迷擃愔械?public static DbProviderFactory GetFactory(string providerInvariantName);可以通過providerInvariantName來(lái)創(chuàng)建對(duì)應(yīng)的 ?ClientFactory,因?yàn)樵摲椒ǚ祷谼bProviderFactory ,同時(shí)SqlClientFactory、MySqlClientFactory等都繼承DbProviderFactory,如下圖所示:
我們通過該方法拿到對(duì)應(yīng)的DbProviderFactory工廠了 ,也就意味著可以通過providerInvariantName拿到對(duì)應(yīng)數(shù)據(jù)庫(kù)的ClientFactory,然后調(diào)用里面的CreateConnection()方法就可以得到一個(gè)DbConnection,再調(diào)用里面的ConnectionString屬性,把鏈接字符串賦值給該屬性即可。該部分的代碼在上面測(cè)試項(xiàng)目System.Data.CommonExts中,代碼如下:
using MySql.Data.MySqlClient;
using System.Data.Common;
using System.Data.SqlClient;
namespace System.Data.CommonExts
{
? ? public static class DbProviderFactories
? ? {
? ? ? ? /// <summary>
? ? ? ? /// 通過在appsettings.json文件中配置 "providerName",來(lái)創(chuàng)建對(duì)應(yīng)的數(shù)據(jù)庫(kù)鏈接
? ? ? ? /// </summary>
? ? ? ? /// <param name="providerInvariantName">例如:MySql.Data.MySqlClient</param>
? ? ? ? /// <returns>DbProviderFactory</returns>
? ? ? ? public static DbProviderFactory GetFactory(string providerInvariantName)
? ? ? ? {
? ? ? ? ? ? if (string.IsNullOrEmpty(providerInvariantName)) throw new Exception("數(shù)據(jù)庫(kù)鏈接字符串配置不正確!");
? ? ? ? ? ?
? ? ? ? ? ? if(providerInvariantName.ToLower().Contains("mysql"))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? return new MySqlClientFactory();
? ? ? ? ? ? }
? ? ? ? ? ? else if(providerInvariantName.ToLower().Contains("sql"))
? ? ? ? ? ? {
? ? ? ? ? ? ? ? return ?SqlClientFactory.Instance;
? ? ? ? ? ? }
? ? ? ? ? ? throw new Exception("暫不支持您使用的數(shù)據(jù)庫(kù)類型!");
? ? ? ? }
? ? }
}
注意,這里需要安裝的包,如下:
4)配置文件配置如下:
{ ?"db": { ??"mysql": { ? ?
?"conStr": "server=.;charset=gb2312;user id=root;password=123456;persist security info=True;database=dappertest;charset=utf8;", ? ? ?"providerName": "MySql.Data.MySqlClient"}} }
我知道你會(huì)想,為什么要這樣做???神經(jīng)病吧!!!,如果你有好的辦法也可以分享出來(lái),后面會(huì)介紹為什么我要這樣封裝。
好了,完成上面的三步即可完成遷移,下面是在測(cè)試時(shí)遇到的問題,在講測(cè)試時(shí)遇到的問題前,需要給大家介紹一下,為什么我要這樣封裝Dapper以及正式項(xiàng)目中為什么要這樣搭建。
三、對(duì)Dapper進(jìn)行封裝的原因以及正式項(xiàng)目中搭建這樣的框架的背景
(1)如果不對(duì)Dapper進(jìn)行二次封裝,我們是這樣使用的
using(MySqlConnection con = new MySqlConnection("server=127.0.0.1;database=test;uid=root;pwd=;charset='gbk'")) { ? var list=con.Query<User>("select * from user");............ }每次對(duì)數(shù)據(jù)庫(kù)操作,我都需要先new一個(gè)MySqlConnection,太煩。于是就有了,下面的代碼:
圖中的ConnectionStringSettings是沒有找到對(duì)應(yīng)程序集時(shí),自己定義的。現(xiàn)在在.Net Core2.0中可以找到了,上面已經(jīng)介紹了。
?(2)我現(xiàn)在使用的是MySQL數(shù)據(jù)庫(kù),如果要切換數(shù)據(jù)庫(kù),比如使用SqlServer、oracle等其他數(shù)據(jù)庫(kù),我還需要修改connection,太麻煩,于是就有了下面的代碼:
通過DBProviderFactories,動(dòng)態(tài)創(chuàng)建數(shù)據(jù)庫(kù)鏈接。
(3)在沒有對(duì)Dapper進(jìn)行二次封裝,如果我們切換數(shù)據(jù)庫(kù),由于不同數(shù)據(jù)庫(kù)的語(yǔ)法不一樣,修改的工作量不能忽視,如何屏蔽不同數(shù)據(jù)庫(kù)之間語(yǔ)法的不同呢,于是就有了下面的代碼:
public interface IDataAdapter
? ? {
? ? ? ? string BindVariablePrefix { get; }
? ? ? ? void AppendColumnName(StringBuilder sb, string columnName);
? ? ? ? void AppendColumnNameEqualsValue(StringBuilder sb, string columnName);
? ? ? ? void AppendUpdateColumnName(StringBuilder sb, string columnName);
? ? }
?public class MySqlDataAdapter : IDataAdapter
? ? {
? ? ? ? public string BindVariablePrefix
? ? ? ? {
? ? ? ? ? ? get { return "@"; }
? ? ? ? }
? ? ? ? public void AppendColumnName(StringBuilder sb, string columnName)
? ? ? ? {
? ? ? ? ? ? sb.AppendFormat("{0}, ", columnName.ToUpper());
? ? ? ? }
? ? ? ? public void AppendColumnNameEqualsValue(StringBuilder sb, string columnName)
? ? ? ? {
? ? ? ? ? ? sb.AppendFormat("{0}{1}, ", BindVariablePrefix, columnName.ToUpper());
? ? ? ? }
? ? ? ? public void AppendUpdateColumnName(StringBuilder sb, string columnName)
? ? ? ? {
? ? ? ? ? ? sb.AppendFormat("{0}={1}{0}, ", columnName.ToUpper(), BindVariablePrefix);
? ? ? ? }
? ? }
下面是真實(shí)項(xiàng)目的整體框架,如下圖:
不是說這樣的搭建是好的,可以適合任何的項(xiàng)目,只能說,它適合我,適合現(xiàn)在的需求。現(xiàn)在的web已經(jīng)是一個(gè)泛化的web,網(wǎng)站不是web的全部分,只是web的一小部分。現(xiàn)在的產(chǎn)品是一個(gè)web產(chǎn)品矩陣,不僅包括網(wǎng)站而且還包括iOS、Android、微信、微信小程序等。所以把接口單獨(dú)分離出來(lái),到時(shí)候可以單獨(dú)部署在一臺(tái)服務(wù)器上,作為公共服務(wù),不僅我們的網(wǎng)站可以使用,而且我們的小程序也可以使用。好了,有點(diǎn)扯了,說的不對(duì)的還請(qǐng)各位指出來(lái)。
四、測(cè)試時(shí)遇到的問題
?(1)鏈接字符串server=.需要修改為:server=127.0.0.1; 否則會(huì)報(bào)鏈接不上數(shù)據(jù)庫(kù)的錯(cuò)誤,這里就不截圖了。
(2)鏈接字符串需要加上SslMode=None
最后完整的配置文件如下:
1 {2 "db": {
3 "mysql": {
4 "conStr": "server=127.0.0.1;charset=gb2312;user id=root;password=123456;persist security info=True;database=dappertest;charset=utf8;SslMode=None",
5 "providerName": "MySql.Data.MySqlClient"
6 ? ?} ? ?
7 ?} ?
8 }
講到這里基本上就講完了,大家如果遇到問題了,可以留言,我看到后會(huì)及時(shí)回復(fù)大家。
五、總結(jié)
通過上面的講解,我們不要為了使用ORM而使用ORM,而忘記了他們底層使用的是ADO.Net,把他們搞明白,比任何ORM都重要!!!,謝謝大家,希望對(duì)你有幫助!
原文地址:http://www.cnblogs.com/runningsmallguo/p/7430693.html
.NET社區(qū)新聞,深度好文,微信中搜索dotNET跨平臺(tái)或掃描二維碼關(guān)注
總結(jié)
以上是生活随笔為你收集整理的.Net Core2.0下使用Dapper遇到的问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .NET中的高性能应用
- 下一篇: .NET跨平台实践:Linux .Net