欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

[开源]Dapper Repository 一种实现方式

程序员文章站 2022-03-20 08:54:08
1. 接着上篇 "[开源]Entity Framework 6 Repository 一种实现方式" 2. 由于Dapper 本身就是轻量级Orm特性,这里参考 " Creating a Data Repository using Dapper " "dynamic queries in dappe ......
  1. 接着上篇[开源]entity framework 6 repository 一种实现方式
  2. 由于dapper 本身就是轻量级orm特性,这里参考creating a data repository using dapper 代码,来解决实体类与expression<func<t, bool>> predicate问题;
  3. 您可以通过nuget:install-package masterchief.dotnet.core.dapper;
  4. 您可以通过github:masterchief 查看具体源码以及单元测试;
  5. 欢迎star,欢迎issues;

插播一条求职

  1. 小弟拥有多年c#开发经验,从事过路灯,消防平台物联网平台开发,坐标上海;
  1. 如果贵司在招聘,烦请大佬考虑下,联系邮箱: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);
        }
    }
}

结语

  1. dapper与entity framework都是通过irepository实现,所以您可以通过ioc切换;
  2. 该篇的单元测试写法与上篇一致;
  3. 小弟不才,大佬轻拍;