一、前期環境準備

1、建立一個core webapi的專案,基於core3.1版本建立一個專案。

2、Dapper安裝,使用NuGet來安裝Dapper程式包

  Install-Package Dapper -Version 2.0.30

  Install-Package Dapper.Contrib -Version 2.0.30

3、MySQL.Data的程式包(可以使用其他資料庫,如:sqlserver,sqllite等)

  Install-Package Dapper -Version 8.0.25

4、appsettings.json檔案中新增連結資料庫的字串(其他資料庫連線字串,自行更改):

"ConnectionStrings": {
  "DefaultConnection": "server=伺服器;port=埠號;database=regatta{0};SslMode=None;uid=userName;pwd=passWord;Allow User Variables=true"
}

二、封裝

1、IDapperContext:

/// <summary>
/// Dapper上下文
/// </summary>
public interface IDapperContext : IDisposable
{
/// <summary>
/// 資料庫連線物件
/// </summary>
IDbConnection ReadConnection { get; } /// <summary>
/// 資料庫連線物件
/// </summary>
IDbConnection WriteConnection { get; }
}

2、DapperContext:

public class DapperContext : IDapperContext
{
/// <summary>
/// 讀連線字串
/// </summary>
private string _readConnectionString; /// <summary>
/// 寫連線字串
/// </summary>
private string _writeConnectionString; private bool _useMiniProfiling; /// <summary>
/// 讀連線
/// </summary>
private IDbConnection _readConnection; /// <summary>
/// 寫連線
/// </summary>
private IDbConnection _wrteConnection; /// <summary>
/// 配置
/// </summary>
private readonly AppSetting _appSetting; /// <summary>
/// 建構函式注入IOptions
/// </summary>
/// <param name="appSetting"></param>
public DapperContext(IOptions<AppSetting> appSetting)
{
_appSetting = appSetting.Value;
_readConnectionString = _appSetting.ReadOnlyConnectionString;
_writeConnectionString = _appSetting.SetConnectionString;
_useMiniProfiling = _appSetting.UseMiniProfiling;
} /// <summary>
/// 連線字串
/// </summary>
/// <param name="connectionString">讀寫連線字串</param>
public DapperContext(string connectionString)
{
_readConnectionString = connectionString;
_writeConnectionString = connectionString;
} #region 讀 /// <summary>
/// 獲取連線
/// </summary>
public IDbConnection ReadConnection
{
get
{
if (_readConnection == null || _readConnection.State == ConnectionState.Closed)
{
if (_useMiniProfiling)
{
_readConnection = new ProfiledDbConnection(new MySqlConnection(_readConnectionString), MiniProfiler.Current);
}
else
{
_readConnection = new MySqlConnection(_readConnectionString);
}
}
if (_readConnection.State != ConnectionState.Open)
{
_readConnection.Open();
}
return _readConnection;
}
} /// <summary>
/// 釋放連線
/// </summary>
public void Dispose()
{
if (_readConnection != null && _readConnection.State == ConnectionState.Open)
_readConnection.Close();
if (_wrteConnection != null && _wrteConnection.State == ConnectionState.Open)
_wrteConnection.Close();
} #endregion #region 寫 /// <summary>
/// 獲取連線
/// </summary>
public IDbConnection WriteConnection
{
get
{
if (_wrteConnection == null || _wrteConnection.State == ConnectionState.Closed)
{
if (_useMiniProfiling)
{
_wrteConnection = new ProfiledDbConnection(new MySqlConnection(_writeConnectionString), MiniProfiler.Current);
}
else
{
_wrteConnection = new MySqlConnection(_writeConnectionString);
}
}
if (_wrteConnection.State != ConnectionState.Open)
{
_wrteConnection.Open();
}
return _wrteConnection;
}
} #endregion
}

3、IRepository(倉儲):

 /// <summary>
/// 資料庫CRUD等操作
/// </summary>
/// <typeparam name="T"></typeparam>
public interface IRepository<T> where T : class
{
/// <summary>
/// 上下文
/// </summary>
IDapperContext Context { get; } /// <summary>
/// 只讀連線
/// </summary>
IDbConnection ReadConnection { get; } /// <summary>
/// 讀寫連線
/// </summary>
IDbConnection WriteConnection { get; } /// <summary>
/// 獲取分頁資料
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="criteria">查詢設定</param>
/// <param name="param"></param>
/// <returns></returns>
PageDataView<TEntity> GetPageData<TEntity>(PageCriteria criteria, object param = null) where TEntity : class; /// <summary>
///
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="criteria"></param>
/// <param name="param"></param>
/// <returns></returns>
PageDataView<TEntity> GetAllData<TEntity>(PageCriteria criteria, object param = null) where TEntity : class; /// <summary>
/// 新增資料
/// </summary>
/// <param name="entity"></param>
/// <param name="transaction"></param>
/// <param name="commandTimeout"></param>
/// <returns></returns>
long Add(T entity, IDbTransaction transaction = null, int? commandTimeout = null); /// <summary>
/// 批量新增資料
/// </summary>
/// <param name="entity"></param>
/// <param name="transaction"></param>
/// <param name="commandTimeout"></param>
/// <returns></returns>
long BatchAdd(IEnumerable<T> list, IDbTransaction transaction = null, int? commandTimeout = null); /// <summary>
///
/// </summary>
/// <param name="entity"></param>
/// <param name="transaction"></param>
/// <param name="commandTimeout"></param>
bool Update(T entity, IDbTransaction transaction = null, int? commandTimeout = null); /// <summary>
/// 刪除單條資料
/// </summary>
/// <param name="entity"></param>
/// <param name="transaction"></param>
/// <param name="commandTimeout"></param>
bool Remove(T entity, IDbTransaction transaction = null, int? commandTimeout = null); /// <summary>
/// 批量刪除
/// </summary>
/// <param name="list"></param>
/// <param name="transaction"></param>
/// <param name="commandTimeout"></param>
/// <returns></returns>
bool BatchRemove(IEnumerable<T> list, IDbTransaction transaction = null, int? commandTimeout = null); /// <summary>
/// 根據主鍵獲取資料
/// </summary>
/// <param name="key"></param>
/// <param name="transaction"></param>
/// <param name="commandTimeout"></param>
/// <returns></returns>
T GetByKey(object key, IDbTransaction transaction = null, int? commandTimeout = null); /// <summary>
/// 獲取所有資料
/// </summary>
/// <param name="transaction"></param>
/// <param name="commandTimeout"></param>
/// <returns></returns>
IEnumerable<T> GetAll(IDbTransaction transaction = null, int? commandTimeout = null); /// <summary>
/// 根據條件獲取資料列表
/// </summary>
/// <param name="sql"></param>
/// <param name="param"></param>
/// <param name="transaction"></param>
/// <param name="commandTimeout"></param>
/// <returns></returns>
IEnumerable<T> GetBy(object sql = null, object param = null, IDbTransaction transaction = null, int? commandTimeout = null); /// <summary>
/// 查詢資料列表
/// </summary>
/// <param name="sql"></param>
/// <param name="transaction"></param>
/// <param name="commandTimeout"></param>
/// <returns></returns>
IEnumerable<dynamic> Query(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null); /// <summary>
/// 多物件查詢
/// </summary>
/// <param name="sql"></param>
/// <param name="param"></param>
/// <param name="transaction"></param>
/// <param name="commandTimeout"></param>
/// <param name="commandType"></param>
/// <returns></returns>
GridReader QueryMultiple(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null); /// <summary>
/// 執行sql
/// </summary>
/// <param name="sql"></param>
/// <param name="transaction"></param>
/// <param name="commandTimeout"></param>
/// <returns></returns>
int Excute(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null); /// <summary>
/// 執行是否存在資料
/// </summary>
/// <param name="sqlStr">查詢(例:SELECT COUNT(1) FROM XXX )</param>
/// <returns></returns>
bool Exists(string sqlStr, object param = null);
}

4、Repository(倉儲實現):

public class Repository<T> : IRepository<T> where T : class
{
public Repository(IDapperContext context)
{
Context = context;
} public IDapperContext Context { get; private set; }
public IDbConnection ReadConnection => Context.ReadConnection; public IDbConnection WriteConnection => Context.WriteConnection; public PageDataView<TEntity> GetPageData<TEntity>(PageCriteria criteria, object param = null) where TEntity : class
{
var p = new DynamicParameters();
string proName = "ProcGetPageData";
p.Add("_tables", criteria.TableName);
p.Add("_fields", criteria.Fields);
p.Add("_where", criteria.Condition);
p.Add("_pageIndex", criteria.CurrentPage);
p.Add("_pageSize", criteria.PageSize);
p.Add("_orderby", criteria.Sort);
p.Add("_totalcount", dbType: DbType.Int32, direction: ParameterDirection.Output);
p.Add("_pagecount", dbType: DbType.Int32, direction: ParameterDirection.Output);
var pageData = new PageDataView<TEntity>(); pageData.Items = ReadConnection.Query<TEntity>(proName, p, commandType: CommandType.StoredProcedure, commandTimeout: 300).ToList();
pageData.TotalNum = p.Get<int>("_totalcount");
pageData.TotalPageCount = p.Get<int>("_pagecount"); //Convert.ToInt32(Math.Ceiling(pageData.TotalNum * 1.0 / criteria.PageSize));
pageData.CurrentPage = criteria.CurrentPage > pageData.TotalPageCount ? pageData.TotalPageCount : criteria.CurrentPage; return pageData;
} public PageDataView<TEntity> GetAllData<TEntity>(PageCriteria criteria, object param = null) where TEntity : class
{
var p = new DynamicParameters();
string proName = "ProcGetAllData";
p.Add("_tables", criteria.TableName);
p.Add("_fields", criteria.Fields);
p.Add("_where", criteria.Condition);
p.Add("_orderby", criteria.Sort);
p.Add("_totalcount", dbType: DbType.Int32, direction: ParameterDirection.Output);
var pageData = new PageDataView<TEntity>();
pageData.Items = ReadConnection.Query<TEntity>(proName, p, commandType: CommandType.StoredProcedure, commandTimeout: 300).ToList();
pageData.TotalNum = p.Get<int>("_totalcount");
return pageData;
} public long Add(T entity, IDbTransaction transaction = null, int? commandTimeout = null)
{
if (entity == null)
{
throw new ArgumentNullException("entity", "Add to DB null entity");
}
var res = WriteConnection.Insert(entity, transaction: transaction, commandTimeout: commandTimeout);
return res;
} public long BatchAdd(IEnumerable<T> list, IDbTransaction transaction = null, int? commandTimeout = null)
{
if (list == null)
{
throw new ArgumentNullException("list", "BatchAdd to DB null entity");
}
var res = WriteConnection.Insert(list, transaction: transaction, commandTimeout: commandTimeout);
return res;
} public virtual bool Update(T entity, IDbTransaction transaction = null, int? commandTimeout = null)
{
if (entity == null)
{
throw new ArgumentNullException("entity", "Update in DB null entity");
}
return WriteConnection.Update(entity, transaction: transaction, commandTimeout: commandTimeout);
} public virtual bool Remove(T entity, IDbTransaction transaction = null, int? commandTimeout = null)
{
if (entity == null)
{
throw new ArgumentNullException("entity", "Remove in DB null entity");
}
return WriteConnection.Delete(entity, transaction: transaction, commandTimeout: commandTimeout);
} public bool BatchRemove(IEnumerable<T> list, IDbTransaction transaction = null, int? commandTimeout = null)
{
if (list == null)
{
throw new ArgumentNullException("list", "BatchAdd to DB null entity");
}
return WriteConnection.Delete(list, transaction: transaction, commandTimeout: commandTimeout);
} public virtual T GetByKey(object queryId, IDbTransaction transaction = null, int? commandTimeout = null)
{
if (queryId == null)
{
throw new ArgumentNullException("queryId");
}
return ReadConnection.Get<T>(queryId, transaction: transaction, commandTimeout: commandTimeout);
} public virtual IEnumerable<T> GetAll(IDbTransaction transaction = null, int? commandTimeout = null)
{
return ReadConnection.GetAll<T>(transaction: transaction, commandTimeout: commandTimeout);
} public virtual IEnumerable<T> GetBy(object sql = null, object param = null, IDbTransaction transaction = null, int? commandTimeout = null)
{
return ReadConnection.Query<T>(sql.ToString(), param, commandTimeout: commandTimeout);
} public IEnumerable<dynamic> Query(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null)
{
return ReadConnection.Query<dynamic>(sql, param);
} public GridReader QueryMultiple(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
{
return ReadConnection.QueryMultiple(sql, param, transaction, commandTimeout, commandType);
} public int Excute(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null)
{
return WriteConnection.Execute(sql, param, transaction: transaction);
} public bool Exists(string sqlStr, object param = null)
{
return ReadConnection.Query<dynamic>(sqlStr, param).Count() > 0 ? true : false;
}
}

利用工廠模式建立倉庫

5、IFactoryRepository:

    /// <summary>
/// 建立倉庫介面
/// </summary>
public interface IFactoryRepository
{
/// <summary>
/// 建立倉庫
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="context"></param>
/// <returns></returns>
IRepository<T> CreateRepository<T>(IDapperContext context) where T : class;
} /// <summary>
/// 工廠
/// </summary>
public class FactoryRepository : IFactoryRepository
{
/// <summary>
/// 建立Repository
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="context"></param>
/// <returns></returns>
public IRepository<T> CreateRepository<T>(IDapperContext context) where T : class
{
IRepository<T> repository = new Repository<T>(context);
return repository;
}
}