- 接着上篇[開源]Entity Framework 6 Repository 一種實現方式
- 因爲Dapper 自己就是輕量級Orm特性,這裏參考Creating a Data Repository using Dapper dynamic queries in dapper 代碼,來解決實體類與Expression<Func<T, bool>> predicate問題;
- 您能夠經過Nuget:Install-Package MasterChief.DotNet.Core.Dapper;
- 您能夠經過GitHub:MasterChief 查看具體源碼以及單元測試;
- 歡迎Star,歡迎Issues;
插播一條求職
- 小弟擁有多年C#開發經驗,從事過路燈,消防平臺物聯網平臺開發,座標上海;
- 若是貴司在招聘,煩請大佬考慮下,聯繫郵箱:MeetYan@outlook.com;
基於Dapper 的Repository實現
public abstract class DapperDbContextBase : IDbContext
{
#region Constructors
/// <summary>
/// 構造函數
/// </summary>
/// <param name="connectString">鏈接字符串</param>
protected DapperDbContextBase(string connectString)
{
ConnectString = connectString;
}
#endregion Constructors
#region Properties
/// <summary>
/// 獲取 是否開啓事務提交
/// </summary>
public IDbTransaction CurrentTransaction { get; private set; }
#endregion Properties
#region Fields
/// <summary>
/// 當前數據庫鏈接
/// </summary>
public IDbConnection CurrentConnection =>
TransactionEnabled ? CurrentTransaction.Connection : CreateConnection();
/// <summary>
/// 獲取 是否開啓事務提交
/// </summary>
public bool TransactionEnabled => CurrentTransaction != null;
/// <summary>
/// 鏈接字符串
/// </summary>
protected readonly string ConnectString;
#endregion Fields
#region Methods
/// <summary>
/// 顯式開啓數據上下文事務
/// </summary>
/// <param name="isolationLevel">指定鏈接的事務鎖定行爲</param>
public void BeginTransaction(IsolationLevel isolationLevel = IsolationLevel.Unspecified)
{
if (!TransactionEnabled) CurrentTransaction = CreateConnection().BeginTransaction(isolationLevel);
}
/// <summary>
/// 提交當前上下文的事務更改
/// </summary>
/// <exception cref="DataAccessException">提交數據更新時發生異常:" + msg</exception>
public void Commit()
{
if (TransactionEnabled)
try
{
CurrentTransaction.Commit();
}
catch (Exception ex)
{
if (ex.InnerException?.InnerException is SqlException sqlEx)
{
var msg = DataBaseHelper.GetSqlExceptionMessage(sqlEx.Number);
throw new DataAccessException("提交數據更新時發生異常:" + msg, sqlEx);
}
throw;
}
}
/// <summary>
/// 建立記錄
/// </summary>
/// <param name="entity">須要操做的實體類</param>
/// <returns>操做是否成功</returns>
public bool Create<T>(T entity)
where T : ModelBase
{
ValidateOperator.Begin().NotNull(entity, "須要新增的數據記錄");
// insert single data always return 0 but the data is inserted in database successfully
//https://github.com/StackExchange/Dapper/issues/587
//List<T> data = new List<T>() { entity };
return CurrentConnection.Insert(new List<T> {entity}, CurrentTransaction) > 0;
#region 測試代碼
//string sql = @"INSERT INTO [dbo].[EFSample]
// ([ID]
// ,[CreateTime]
// ,[ModifyTime]
// ,[Available]
// ,[UserName])
//VALUES
// (@ID
// ,@CreateTime
// ,@ModifyTime
// ,@Available
// ,@UserName)";
//return CurrentConnection.Execute(sql, entity) > 0;
#endregion 測試代碼
}
/// <summary>
/// 建立數據庫鏈接IDbConnection
/// </summary>
/// <returns></returns>
public abstract IDbConnection CreateConnection();
/// <summary>
/// 刪除記錄
/// </summary>
/// <returns>操做是否成功</returns>
/// <param name="entity">須要操做的實體類.</param>
public bool Delete<T>(T entity)
where T : ModelBase
{
ValidateOperator.Begin().NotNull(entity, "須要刪除的數據記錄");
return CurrentConnection.Delete(entity);
}
/// <summary>
/// 執行與釋放或重置非託管資源關聯的應用程序定義的任務。
/// </summary>
public void Dispose()
{
if (CurrentTransaction != null)
{
CurrentTransaction.Dispose();
CurrentTransaction = null;
}
CurrentConnection?.Dispose();
}
/// <summary>
/// 條件判斷是否存在
/// </summary>
/// <returns>是否存在</returns>
/// <param name="predicate">判斷條件委託</param>
public bool Exist<T>(Expression<Func<T, bool>> predicate = null)
where T : ModelBase
{
var tableName = GetTableName<T>();
var queryResult = DynamicQuery.GetDynamicQuery(tableName, predicate);
var result =
CurrentConnection.ExecuteScalar(queryResult.Sql, (object) queryResult.Param, CurrentTransaction);
return result != null;
}
/// <summary>
/// 根據id獲取記錄
/// </summary>
/// <returns>記錄</returns>
/// <param name="id">id.</param>
public T GetByKeyId<T>(object id)
where T : ModelBase
{
ValidateOperator.Begin().NotNull(id, "Id");
return CurrentConnection.Get<T>(id, CurrentTransaction);
}
/// <summary>
/// 條件獲取記錄集合
/// </summary>
/// <returns>集合</returns>
/// <param name="predicate">篩選條件.</param>
public List<T> GetList<T>(Expression<Func<T, bool>> predicate = null)
where T : ModelBase
{
var tableName = GetTableName<T>();
var queryResult = DynamicQuery.GetDynamicQuery(tableName, predicate);
return CurrentConnection.Query<T>(queryResult.Sql, (object) queryResult.Param, CurrentTransaction).ToList();
}
/// <summary>
/// 條件獲取記錄第一條或者默認
/// </summary>
/// <returns>記錄</returns>
/// <param name="predicate">篩選條件.</param>
public T GetFirstOrDefault<T>(Expression<Func<T, bool>> predicate = null)
where T : ModelBase
{
var tableName = GetTableName<T>();
var queryResult = DynamicQuery.GetDynamicQuery(tableName, predicate);
return CurrentConnection.QueryFirst<T>(queryResult.Sql, (object) queryResult.Param, CurrentTransaction);
}
/// <summary>
/// 條件查詢
/// </summary>
/// <returns>IQueryable</returns>
/// <param name="predicate">篩選條件.</param>
public IQueryable<T> Query<T>(Expression<Func<T, bool>> predicate = null)
where T : ModelBase
{
throw new NotImplementedException();
}
/// <summary>
/// 顯式回滾事務,僅在顯式開啓事務後有用
/// </summary>
public void Rollback()
{
if (TransactionEnabled) CurrentTransaction.Rollback();
}
/// <summary>
/// 執行Sql 腳本查詢
/// </summary>
/// <param name="sql">Sql語句</param>
/// <param name="parameters">參數</param>
/// <returns>集合</returns>
public IEnumerable<T> SqlQuery<T>(string sql, IDbDataParameter[] parameters)
{
ValidateOperator.Begin()
.NotNullOrEmpty(sql, "Sql語句");
var dataParameters = CreateParameter(parameters);
return CurrentConnection.Query<T>(sql, dataParameters, CurrentTransaction);
}
/// <summary>
/// 根據記錄
/// </summary>
/// <returns>操做是否成功.</returns>
/// <param name="entity">實體類記錄.</param>
public bool Update<T>(T entity)
where T : ModelBase
{
ValidateOperator.Begin().NotNull(entity, "須要更新的數據記錄");
return CurrentConnection.Update(entity, CurrentTransaction);
}
private DapperParameter CreateParameter(IDbDataParameter[] parameters)
{
if (!(parameters?.Any() ?? false)) return null;
var dataParameters = new DapperParameter();
foreach (var parameter in parameters) dataParameters.Add(parameter);
return dataParameters;
}
private string GetTableName<T>()
where T : ModelBase
{
var tableCfgInfo = AttributeHelper.Get<T, TableAttribute>();
return tableCfgInfo != null ? tableCfgInfo.Name.Trim() : typeof(T).Name;
}
#endregion Methods
}
使用方法
public class SampleService : ISampleService
{
private readonly IDatabaseContextFactory _contextFactory;
public SampleService(IDatabaseContextFactory contextFactory)
{
_contextFactory = contextFactory;
}
/// <summary>
/// 建立
/// </summary>
/// <param name="sample">EFSample</param>
/// <returns></returns>
public bool Create(EfSample sample)
{
using (IDbContext context = _contextFactory.Create())
{
return context.Create(sample);
}
}
/// <summary>
/// 條件查詢
/// </summary>
/// <param name="predicate">The predicate.</param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public EfSample GetFirstOrDefault(Expression<Func<EfSample, bool>> predicate = null)
{
using (IDbContext context = _contextFactory.Create())
{
return context.GetFirstOrDefault(predicate);
}
}
/// <summary>
/// 根據主鍵查詢
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public EfSample GetByKeyId(Guid id)
{
using (IDbContext context = _contextFactory.Create())
{
return context.GetByKeyId<EfSample>(id);
}
}
/// <summary>
/// 條件查詢集合
/// </summary>
/// <param name="predicate">The predicate.</param>
/// <returns></returns>
public List<EfSample> GetList(Expression<Func<EfSample, bool>> predicate = null)
{
using (IDbContext context = _contextFactory.Create())
{
return context.GetList(predicate);
}
}
/// <summary>
/// 添加判斷是否存在
/// </summary>
/// <param name="predicate">The predicate.</param>
/// <returns></returns>
public bool Exist(Expression<Func<EfSample, bool>> predicate = null)
{
using (IDbContext context = _contextFactory.Create())
{
return context.Exist(predicate);
}
}
/// <summary>
/// 腳本查詢
/// </summary>
/// <param name="sql">The SQL.</param>
/// <param name="parameter">DbParameter[]</param>
/// <returns></returns>
public List<EfSample> SqlQuery(string sql, DbParameter[] parameter)
{
using (IDbContext context = _contextFactory.Create())
{
return context.SqlQuery<EfSample>(sql, parameter)?.ToList();
}
}
/// <summary>
/// 更新
/// </summary>
/// <param name="sample">The sample.</param>
/// <returns></returns>
public bool Update(EfSample sample)
{
using (IDbContext context = _contextFactory.Create())
{
return context.Update(sample);
}
}
/// <summary>
/// 事務
/// </summary>
/// <param name="sample">The sample.</param>
/// <param name="sample2">The sample2.</param>
/// <returns></returns>
public bool CreateWithTransaction(EfSample sample, EfSample sample2)
{
bool result;
using (IDbContext context = _contextFactory.Create())
{
try
{
context.BeginTransaction();//開啓事務
context.Create(sample);
context.Create(sample2);
context.Commit();
result = true;
}
catch (Exception)
{
context.Rollback();
result = false;
}
}
return result;
}
/// <summary>
/// 刪除
/// </summary>
/// <param name="sample"></param>
/// <returns></returns>
public bool Delete(EfSample sample)
{
using (IDbContext context = _contextFactory.Create())
{
return context.Delete(sample);
}
}
}
結語
- Dapper與Entity Framework都是經過IRepository實現,因此您能夠經過Ioc切換;
- 該篇的單元測試寫法與上篇一致;
- 小弟不才,大佬輕拍;