当前位置: 移动技术网 > IT编程>开发语言>.net > 基于Dapper二次封装了一个易用的ORM工具类:SqlDapperUtil

基于Dapper二次封装了一个易用的ORM工具类:SqlDapperUtil

2018年09月03日  | 移动技术网IT编程  | 我要评论

网游之侠义天下下载,今日废铜价格行情,好心作怪30集

基于dapper二次封装了一个易用的orm工具类:sqldapperutil,把日常能用到的各种crud都进行了简化封装,让普通程序员只需关注业务即可,因为非常简单,故直接贴源代码,大家若需使用可以直接复制到项目中,该sqldapperutil已广泛用于公司项目中。

using system;
using system.collections.generic;
using system.linq;
using system.text;
using system.threading.tasks;
using dapper;
using system.data;
using system.data.common;
using system.reflection;
using system.io;
using system.collections.concurrent;
using system.data.sqlclient;

namespace zuowj.common
{
    /// <summary>
    /// 基于dapper的数据操作类封装的工具类
    /// author:左文俊
    /// date:2017/12/11
    /// </summary>
    public class sqldapperutil
    {
        private static string dbconnectionstringconfigpath = null;
        private readonly static concurrentdictionary<string, bool> dbconnnamescachedic = new concurrentdictionary<string, bool>();

        private string dbconnectionname = null;
        private string dbconnectionstring = null;
        private string dbprovidername = null;
        private idbconnection dbconnection = null;
        private bool usedbtransaction = false;
        private idbtransaction dbtransaction = null;


        #region 私有方法

        private idbconnection getdbconnection()
        {
            bool needcreatenew = false;
            if (dbconnection == null || string.isnullorwhitespace(dbconnection.connectionstring))
            {
                needcreatenew = true;
            }
            else if (!memorycacheutil.contains(dbconnectionname))
            {
                needcreatenew = true;
            }

            if (needcreatenew)
            {
                dbconnectionstring = getdbconnectionstring(dbconnectionname, out dbprovidername);
                var dbproviderfactory = dbproviderfactories.getfactory(dbprovidername);
                dbconnection = dbproviderfactory.createconnection();
                dbconnection.connectionstring = dbconnectionstring;
            }

            if (dbconnection.state == connectionstate.closed)
            {
                dbconnection.open();
            }

            return dbconnection;
        }

        private string getdbconnectionstring(string dbconnname, out string dbprovidername)
        {
            //如果指定的连接字符串配置文件路径,则创建缓存依赖,一旦配置文件更改就失效,再重新读取
            string[] conninfos = memorycacheutil.getoraddcacheitem(dbconnname, () =>
            {
                var connstrsettings = configutil.getconnectionstringforconfigpath(dbconnname, sqldapperutil.dbconnectionstringconfigpath);
                string dbprodname = connstrsettings.providername;
                string dbconnstr = connstrsettings.connectionstring;
                //logutil.info(string.format("sqldapperutil.getdbconnectionstring>读取连接字符串配置节点[{0}]:{1},providername:{2}", dbconnname, dbconnstr, dbprodname), "sqldapperutil.getdbconnectionstring");
                return new[] { encryptutil.decrypt(dbconnstr), dbprodname };
            }, sqldapperutil.dbconnectionstringconfigpath);

            dbprovidername = conninfos[1];
            return conninfos[0];
        }


        private t usedbconnection<t>(func<idbconnection, t> queryorexecsqlfunc)
        {
            idbconnection dbconn = null;

            try
            {
                type modeltype = typeof(t);
                var typemap = dapper.sqlmapper.gettypemap(modeltype);
                if (typemap == null || !(typemap is columnattributetypemapper<t>))
                {
                    dapper.sqlmapper.settypemap(modeltype, new columnattributetypemapper<t>());
                }

                dbconn = getdbconnection();
                if (usedbtransaction && dbtransaction == null)
                {
                    dbtransaction = getdbtransaction();
                }

                return queryorexecsqlfunc(dbconn);
            }
            catch
            {
                throw;
            }
            finally
            {
                if (dbtransaction == null && dbconn != null)
                {
                    closedbconnection(dbconn);
                }
            }
        }

        private void closedbconnection(idbconnection dbconn, bool disposed = false)
        {
            if (dbconn != null)
            {
                if (disposed && dbtransaction != null)
                {
                    dbtransaction.rollback();
                    dbtransaction.dispose();
                    dbtransaction = null;
                }

                if (dbconn.state != connectionstate.closed)
                {
                    dbconn.close();
                }
                dbconn.dispose();
                dbconn = null;
            }
        }

        /// <summary>
        /// 获取一个事务对象(如果需要确保多条执行语句的一致性,必需使用事务)
        /// </summary>
        /// <param name="il"></param>
        /// <returns></returns>
        private idbtransaction getdbtransaction(isolationlevel il = isolationlevel.unspecified)
        {
            return getdbconnection().begintransaction(il);
        }

        private dynamicparameters todynamicparameters(dictionary<string, object> paramdic)
        {
            return new dynamicparameters(paramdic);
        }

        #endregion

        public static string dbconnectionstringconfigpath
        {
            get
            {
                if (string.isnullorempty(dbconnectionstringconfigpath))//如果没有指定配置文件,则取默认的配置文件路径作为缓存依赖路径
                {
                    dbconnectionstringconfigpath = baseutil.getconfigpath();
                }

                return dbconnectionstringconfigpath;
            }
            set
            {
                if (!string.isnullorwhitespace(value) && !file.exists(value))
                {
                    throw new filenotfoundexception("指定的db连接字符串配置文件不存在:" + value);
                }

                //如果配置文件改变,则可能导致连接字符串改变,故必需清除所有连接字符串的缓存以便后续重新加载字符串
                if (!string.equals(dbconnectionstringconfigpath, value, stringcomparison.ordinalignorecase))
                {
                    foreach (var item in dbconnnamescachedic)
                    {
                        memorycacheutil.removecacheitem(item.key);
                    }
                }

                dbconnectionstringconfigpath = value;
            }
        }

        public sqldapperutil(string connname)
        {
            dbconnectionname = connname;
            if (!dbconnnamescachedic.containskey(connname)) //如果静态缓存中没有,则加入到静态缓存中
            {
                dbconnnamescachedic[connname] = true;
            }

        }


        /// <summary>
        /// 使用事务
        /// </summary>
        public void usedbtransaction()
        {
            usedbtransaction = true;
        }


        /// <summary>
        /// 获取一个值,param可以是sql参数也可以是匿名对象
        /// </summary>
        /// <typeparam name="t"></typeparam>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <param name="transaction"></param>
        /// <param name="commandtimeout"></param>
        /// <param name="commandtype"></param>
        /// <returns></returns>
        public t getvalue<t>(string sql, object param = null, int? commandtimeout = null, commandtype? commandtype = null)
        {
            return usedbconnection((dbconn) =>
             {
                 return dbconn.executescalar<t>(sql, param, dbtransaction, commandtimeout, commandtype);
             });
        }

        /// <summary>
        /// 获取第一行的所有值,param可以是sql参数也可以是匿名对象
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <param name="transaction"></param>
        /// <param name="commandtimeout"></param>
        /// <param name="commandtype"></param>
        /// <returns></returns>
        public dictionary<string, dynamic> getfirstvalues(string sql, object param = null, int? commandtimeout = null, commandtype? commandtype = null)
        {
            return usedbconnection((dbconn) =>
            {
                dictionary<string, dynamic> firstvalues = new dictionary<string, dynamic>();
                list<string> indexcolnamemappings = new list<string>();
                int rowindex = 0;
                using (var reader = dbconn.executereader(sql, param, dbtransaction, commandtimeout, commandtype))
                {
                    while (reader.read())
                    {
                        if ((++rowindex) > 1) break;
                        if (indexcolnamemappings.count == 0)
                        {
                            for (int i = 0; i < reader.fieldcount; i++)
                            {
                                indexcolnamemappings.add(reader.getname(i));
                            }
                        }

                        for (int i = 0; i < reader.fieldcount; i++)
                        {
                            firstvalues[indexcolnamemappings[i]] = reader.getvalue(i);
                        }
                    }
                    reader.close();
                }

                return firstvalues;

            });
        }

        /// <summary>
        /// 获取一个数据模型实体类,param可以是sql参数也可以是匿名对象
        /// </summary>
        /// <typeparam name="t"></typeparam>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <param name="transaction"></param>
        /// <param name="commandtimeout"></param>
        /// <param name="commandtype"></param>
        /// <returns></returns>
        public t getmodel<t>(string sql, object param = null, int? commandtimeout = null, commandtype? commandtype = null) where t : class
        {
            return usedbconnection((dbconn) =>
            {
                return dbconn.queryfirstordefault<t>(sql, param, dbtransaction, commandtimeout, commandtype);
            });
        }

        /// <summary>
        /// 获取符合条件的所有数据模型实体类列表,param可以是sql参数也可以是匿名对象
        /// </summary>
        /// <typeparam name="t"></typeparam>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <param name="transaction"></param>
        /// <param name="buffered"></param>
        /// <param name="commandtimeout"></param>
        /// <param name="commandtype"></param>
        /// <returns></returns>
        public list<t> getmodellist<t>(string sql, object param = null, bool buffered = true, int? commandtimeout = null, commandtype? commandtype = null) where t : class
        {
            return usedbconnection((dbconn) =>
            {
                return dbconn.query<t>(sql, param, dbtransaction, buffered, commandtimeout, commandtype).tolist();
            });
        }

        /// <summary>
        /// 获取符合条件的所有数据并根据动态构建model类委托来创建合适的返回结果(适用于临时性结果且无对应的模型实体类的情况)
        /// </summary>
        /// <typeparam name="t"></typeparam>
        /// <param name="buildmodelfunc"></param>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <param name="buffered"></param>
        /// <param name="commandtimeout"></param>
        /// <param name="commandtype"></param>
        /// <returns></returns>
        public t getdynamicmodel<t>(func<ienumerable<dynamic>, t> buildmodelfunc, string sql, object param = null, bool buffered = true, int? commandtimeout = null, commandtype? commandtype = null)
        {
            var dynamicresult = usedbconnection((dbconn) =>
           {
               return dbconn.query(sql, param, dbtransaction, buffered, commandtimeout, commandtype);
           });

            return buildmodelfunc(dynamicresult);
        }

        /// <summary>
        /// 获取符合条件的所有指定返回结果对象的列表(复合对象【如:1对多,1对1】),param可以是sql参数也可以是匿名对象
        /// </summary>
        /// <typeparam name="t"></typeparam>
        /// <param name="sql"></param>
        /// <param name="types"></param>
        /// <param name="map"></param>
        /// <param name="param"></param>
        /// <param name="transaction"></param>
        /// <param name="buffered"></param>
        /// <param name="spliton"></param>
        /// <param name="commandtimeout"></param>
        /// <param name="commandtype"></param>
        /// <returns></returns>

        public list<t> getmultmodellist<t>(string sql, type[] types, func<object[], t> map, object param = null, bool buffered = true, string spliton = "id", int? commandtimeout = null, commandtype? commandtype = null)
        {
            return usedbconnection((dbconn) =>
            {
                return dbconn.query<t>(sql, types, map, param, dbtransaction, buffered, spliton, commandtimeout, commandtype).tolist();
            });
        }




        /// <summary>
        /// 执行sql命令(crud),param可以是sql参数也可以是要添加的实体类
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <param name="transaction"></param>
        /// <param name="commandtimeout"></param>
        /// <param name="commandtype"></param>
        /// <returns></returns>
        public bool executecommand(string sql, object param = null, int? commandtimeout = null, commandtype? commandtype = null)
        {
            return usedbconnection((dbconn) =>
            {
                int result = dbconn.execute(sql, param, dbtransaction, commandtimeout, commandtype);
                return (result > 0);
            });
        }

        /// <summary>
        /// 批量转移数据(利用sqlbulkcopy实现快速大批量插入到指定的目的表及sqldataadapter的批量删除)
        /// </summary>
        public bool batchmovedata(string srcselectsql, string srctablename, list<sqlparameter> srcprimarykeyparams, string destconnname, string desttablename)
        {

            using (sqldataadapter srcsqldataadapter = new sqldataadapter(srcselectsql, getdbconnectionstring(dbconnectionname, out dbprovidername)))
            {
                datatable srctable = new datatable();
                sqlcommand deletecommand = null;
                try
                {
                    srcsqldataadapter.acceptchangesduringfill = true;
                    srcsqldataadapter.acceptchangesduringupdate = false;
                    srcsqldataadapter.fill(srctable);

                    if (srctable == null || srctable.rows.count <= 0) return true;

                    string notexistsdestsqlwhere = null;
                    string deletesrcsqlwhere = null;

                    for (int i = 0; i < srcprimarykeyparams.count; i++)
                    {
                        string keycolname = srcprimarykeyparams[i].parametername.replace("@", "");
                        notexistsdestsqlwhere += string.format(" and told.{0}=tnew.{0}", keycolname);
                        deletesrcsqlwhere += string.format(" and {0}=@{0}", keycolname);
                    }

                    string dbprovidername2 = null;
                    using (var destconn = new sqlconnection(getdbconnectionstring(destconnname, out dbprovidername2)))
                    {
                        destconn.open();

                        string tempdesttablename = "#temp_" + desttablename;
                        destconn.execute(string.format("select top 0 * into {0} from {1}", tempdesttablename, desttablename));
                        string destinsertcols = null;
                        using (var destsqlbulkcopy = new sqlbulkcopy(destconn))
                        {
                            try
                            {
                                destsqlbulkcopy.bulkcopytimeout = 120;
                                destsqlbulkcopy.destinationtablename = tempdesttablename;
                                foreach (datacolumn col in srctable.columns)
                                {
                                    destsqlbulkcopy.columnmappings.add(col.columnname, col.columnname);
                                    destinsertcols += "," + col.columnname;
                                }

                                destsqlbulkcopy.batchsize = 1000;
                                destsqlbulkcopy.writetoserver(srctable);
                            }
                            catch (exception ex)
                            {
                                //logutil.error("sqldapperutil.batchmovedata.sqlbulkcopy:" + ex.tostring(), "sqldapperutil.batchmovedata");
                            }

                            destinsertcols = destinsertcols.substring(1);

                            destconn.execute(string.format("insert into {1}({0}) select {0} from {2} tnew where not exists(select 1 from {1} told where {3})",
                                             destinsertcols, desttablename, tempdesttablename, notexistsdestsqlwhere.trim().substring(3)), null, null, 100);
                        }
                        destconn.close();
                    }

                    deletecommand = new sqlcommand(string.format("delete from {0} where {1}", srctablename, deletesrcsqlwhere.trim().substring(3)), srcsqldataadapter.selectcommand.connection);
                    deletecommand.parameters.addrange(srcprimarykeyparams.toarray());
                    deletecommand.updatedrowsource = updaterowsource.none;
                    deletecommand.commandtimeout = 200;

                    srcsqldataadapter.deletecommand = deletecommand;
                    foreach (datarow row in srctable.rows)
                    {
                        row.delete();
                    }

                    srcsqldataadapter.updatebatchsize = 1000;
                    srcsqldataadapter.update(srctable);
                    srctable.acceptchanges();

                    return true;
                }
                catch (exception ex)
                {
                    //logutil.error("sqldapperutil.batchmovedata:" + ex.tostring(), "sqldapperutil.batchmovedata");
                    return false;
                }
                finally
                {
                    if (deletecommand != null)
                    {
                        deletecommand.parameters.clear();
                    }
                }
            }

        }

        /// <summary>
        /// 批量复制数据(把源db中根据sql语句查出的结果批量copy插入到目的db的目的表中)
        /// </summary>
        public tresult batchcopydata<tresult>(string srcselectsql, string destconnname, string desttablename, idictionary<string, string> colmappings, func<idbconnection, tresult> aftercoppyfunc)
        {

            using (sqldataadapter srcsqldataadapter = new sqldataadapter(srcselectsql, getdbconnectionstring(dbconnectionname, out dbprovidername)))
            {
                datatable srctable = new datatable();
                tresult copyresult = default(tresult);
                try
                {
                    srcsqldataadapter.acceptchangesduringfill = true;
                    srcsqldataadapter.acceptchangesduringupdate = false;
                    srcsqldataadapter.fill(srctable);

                    if (srctable == null || srctable.rows.count <= 0) return copyresult;


                    string dbprovidername2 = null;
                    using (var destconn = new sqlconnection(getdbconnectionstring(destconnname, out dbprovidername2)))
                    {
                        destconn.open();
                        string tempdesttablename = "#temp_" + desttablename;
                        destconn.execute(string.format("select top 0 * into {0} from {1}", tempdesttablename, desttablename));
                        bool bcpresult = false;
                        using (var destsqlbulkcopy = new sqlbulkcopy(destconn))
                        {
                            try
                            {
                                destsqlbulkcopy.bulkcopytimeout = 120;
                                destsqlbulkcopy.destinationtablename = tempdesttablename;
                                foreach (var col in colmappings)
                                {
                                    destsqlbulkcopy.columnmappings.add(col.key, col.value);
                                }

                                destsqlbulkcopy.batchsize = 1000;
                                destsqlbulkcopy.writetoserver(srctable);
                                bcpresult = true;
                            }
                            catch (exception ex)
                            {
                                //logutil.error("sqldapperutil.batchmovedata.sqlbulkcopy:" + ex.tostring(), "sqldapperutil.batchmovedata");
                            }
                        }

                        if (bcpresult)
                        {
                            copyresult = aftercoppyfunc(destconn);
                        }

                        destconn.close();
                    }

                    return copyresult;
                }
                catch (exception ex)
                {
                    //logutil.error("sqldapperutil.batchcopydata:" + ex.tostring(), "sqldapperutil.batchcopydata");
                    return copyresult;
                }
            }

        }


        /// <summary>
        /// 当使用了事务,则最后需要调用该方法以提交所有操作
        /// </summary>
        /// <param name="dbtransaction"></param>
        public void commit()
        {
            try
            {
                if (dbtransaction.connection != null && dbtransaction.connection.state != connectionstate.closed)
                {
                    dbtransaction.commit();
                }
            }
            catch
            {
                throw;
            }
            finally
            {
                if (dbtransaction.connection != null)
                {
                    closedbconnection(dbtransaction.connection);
                }
                dbtransaction.dispose();
                dbtransaction = null;
                usedbtransaction = false;

                if (dbconnection != null)
                {
                    closedbconnection(dbconnection);
                }
            }
        }

        /// <summary>
        /// 当使用了事务,如果报错或需要中断执行,则需要调用该方法执行回滚操作
        /// </summary>
        /// <param name="dbtransaction"></param>
        public void rollback()
        {
            try
            {
                if (dbtransaction.connection != null && dbtransaction.connection.state != connectionstate.closed)
                {
                    dbtransaction.rollback();
                }
            }
            catch
            {
                throw;
            }
            finally
            {
                if (dbtransaction.connection != null)
                {
                    closedbconnection(dbtransaction.connection);
                }

                dbtransaction.dispose();
                dbtransaction = null;
                usedbtransaction = false;
            }
        }

        ~sqldapperutil()
        {
            try
            {
                closedbconnection(dbconnection, true);
            }
            catch
            { }
        }

    }
}

columnattributetypemapper辅助类相关代码如下:(如果不考虑实体类的属性与表字段不一致的情况,如下映射类可以不需要添加,同时sqldapperutil中移除相关依赖columnattributetypemapper逻辑即可)

using dapper;
using system;
using system.collections.generic;
using system.linq;
using system.reflection;
using system.text;
using system.threading.tasks;

namespace kyexpress.common
{
    public class columnattributetypemapper<t> : fallbacktypemapper
    {
        public columnattributetypemapper()
            : base(new sqlmapper.itypemap[]
                {
                    new custompropertytypemap(
                       typeof(t),
                       (type, columnname) =>
                           type.getproperties().firstordefault(prop =>
                               prop.getcustomattributes(false)
                                   .oftype<columnattribute>()
                                   .any(attr => attr.name == columnname)
                               )
                       ),
                    new defaulttypemap(typeof(t))
                })
        {
        }
    }

    [attributeusage(attributetargets.property, allowmultiple = true)]
    public class columnattribute : attribute
    {
        public string name { get; set; }
    }

    public class fallbacktypemapper : sqlmapper.itypemap
    {
        private readonly ienumerable<sqlmapper.itypemap> _mappers;

        public fallbacktypemapper(ienumerable<sqlmapper.itypemap> mappers)
        {
            _mappers = mappers;
        }


        public constructorinfo findconstructor(string[] names, type[] types)
        {
            foreach (var mapper in _mappers)
            {
                try
                {
                    constructorinfo result = mapper.findconstructor(names, types);
                    if (result != null)
                    {
                        return result;
                    }
                }
                catch (notimplementedexception)
                {
                }
            }
            return null;
        }

        public sqlmapper.imembermap getconstructorparameter(constructorinfo constructor, string columnname)
        {
            foreach (var mapper in _mappers)
            {
                try
                {
                    var result = mapper.getconstructorparameter(constructor, columnname);
                    if (result != null)
                    {
                        return result;
                    }
                }
                catch (notimplementedexception)
                {
                }
            }
            return null;
        }

        public sqlmapper.imembermap getmember(string columnname)
        {
            foreach (var mapper in _mappers)
            {
                try
                {
                    var result = mapper.getmember(columnname);
                    if (result != null)
                    {
                        return result;
                    }
                }
                catch (notimplementedexception)
                {
                }
            }
            return null;
        }


        public constructorinfo findexplicitconstructor()
        {
            return _mappers
                .select(mapper => mapper.findexplicitconstructor())
                .firstordefault(result => result != null);
        }
    }

}

使用示例方法如下:

 1.先来模拟各种查询数据(由于是直接写模拟sql输出,故没有条件,也便于大家copy后直接可以测试结果)

            //实例化sqldapperutil对象,构造函数是config文件中的connectionstrings的name名
            var dapper = new sqldapperutil("lmsconnectionstring");

            //查询1个值
            datetime nowtime = dapper.getvalue<datetime>("select getdate() as nowtime");


            //查询1行值,并转换成字典(这对于临时查询多个字段而无需定义实体类有用)
            dictionary<string, dynamic> rowvalues = dapper.getfirstvalues("select 0 as col0,1 as col1,2 as col2");


            //查询1行并返回实体类
            person person = dapper.getmodel<person>("select '张三' as name,22 as age,'2018-1-1' as birthday,'中国广东深圳' as homeaddr");


            //查询1行表字段与实体类属性不一致映射
            person person2 = dapper.getmodel<person>("select '张三' as name,22 as age,'2018-1-1' as birthday,'中国广东深圳' as homeaddress");


            //查询多行返回实体集合
            var persons = dapper.getmodellist<person>(@"select '张三' as name,22 as age,'2018-1-1' as birthday,'中国广东深圳' as homeaddr union all
                                                                            select '李四' as name,25 as age,'2018-10-1' as birthday,'中国广东深圳' as homeaddress union all
                                                                            select '王五' as name,35 as age,'1982-10-1' as birthday,'中国广东广州' as homeaddress
                                                                        ");


            //查询多行返回1对1关联实体结果集
            var personwithcarresult = dapper.getmultmodellist<person>(@"select t1.*,t2.* from
                                                                                                    (select '张三' as name,22 as age,'2018-1-1' as birthday,'中国广东深圳' as homeaddr union all
                                                                                                    select '李四' as name,25 as age,'2018-10-1' as birthday,'中国广东深圳' as homeaddress union all
                                                                                                    select '王五' as name,35 as age,'1982-10-1' as birthday,'中国广东广州' as homeaddress)as t1 inner join
                                                                                                    (
                                                                                                    select '张三' as drivername,'大众' as brand,'2018-8-8' as manufacturedate union all
                                                                                                    select '李四' as drivername,'奔驰' as brand,'2018-1-8' as manufacturedate union all
                                                                                                    select '王五' as drivername,'奥迪' as brand,'2017-8-8' as manufacturedate
                                                                                                    )as t2
                                                                                                    on t1.name=t2.drivername
                                                                        ", new[] { typeof(person), typeof(carinfo) }, (objs) =>
                                                                         {
                                                                             person personitem = objs[0] as person;
                                                                             carinfo caritem = objs[1] as carinfo;
                                                                             personitem.car = caritem;
                                                                             return personitem;
                                                                         }, spliton: "drivername");




            //查询多行返回1对多关联实体结果=personwithmanycars
            list<person> personwithmanycars = new list<person>();
            dapper.getmultmodellist<person>(@"select t1.*,t2.* from
                                                                                                    (select '张三' as name,22 as age,'2018-1-1' as birthday,'中国广东深圳' as homeaddr union all
                                                                                                    select '李四' as name,25 as age,'2018-10-1' as birthday,'中国广东深圳' as homeaddress union all
                                                                                                    select '王五' as name,35 as age,'1982-10-1' as birthday,'中国广东广州' as homeaddress)as t1 inner join
                                                                                                    (
                                                                                                    select '张三' as drivername,'大众' as brand,'2018-8-8' as manufacturedate union all
                                                                                                    select '张三' as drivername,'奔驰' as brand,'2018-1-8' as manufacturedate union all
                                                                                                    select '张三' as drivername,'奥迪' as brand,'2017-8-8' as manufacturedate
                                                                                                    )as t2
                                                                                                    on t1.name=t2.drivername
                                                                        ", new[] { typeof(person), typeof(carinfo) }, (objs) =>
                                                                        {
                                                                            person personitem = objs[0] as person;
                                                                            carinfo caritem = objs[1] as carinfo;

                                                                            person personitemmain = personwithmanycars.firstordefault(p => p.name == personitem.name);
                                                                            if (personitemmain == null)
                                                                            {
                                                                                personitem.cars = new list<carinfo>();
                                                                                personitemmain = personitem;
                                                                                personwithmanycars.add(personitemmain);
                                                                            }

                                                                            personitemmain.cars.add(caritem);
                                                                            return personitemmain;

                                                                        }, spliton: "drivername");

2.下面是演示如何进行增、删、改以及动态查询的情况:

            //使用事务创建多张表,多条sql语句写在一起
            try
            {
                dapper.usedbtransaction();
                dapper.executecommand(@"create table t_person(name nvarchar(20) primary key,age int,birthday datetime,homeaddress nvarchar(200));
                                                    create table t_carinfo(drivername nvarchar(20) primary key,brand nvarchar(50),manufacturedate datetime)");
                dapper.commit();
            }
            catch (exception ex)
            {
                dapper.rollback();
                //记日志
            }

            //使用事务批量插入多张表的多个记录,多条sql分多次执行(参数支持批量集合对象传入,无需循环)
            try
            {
                dapper.usedbtransaction();
                dapper.executecommand(@"insert into t_person
select n'张三' as name,22 as age,'2018-1-1' as birthday,n'中国广东深圳' as homeaddress union all
select n'李四' as name,25 as age,'2018-10-1' as birthday,n'中国广东深圳' as homeaddress union all
select n'王五' as name,35 as age,'1982-10-1' as birthday,n'中国广东广州' as homeaddress");


                var carinfos = dapper.getmodellist<carinfo>(@"
select n'张三' as drivername,n'大众' as brand,'2018-8-8' as manufacturedate union all
select n'李四' as drivername,n'奔驰' as brand,'2018-1-8' as manufacturedate union all
select n'王五' as drivername,n'奥迪' as brand,'2017-8-8' as manufacturedate");

                dapper.executecommand(@"insert into t_carinfo(drivername,brand,manufacturedate) values(@drivername,@brand,@manufacturedate)", carinfos);

                dapper.commit();
            }
            catch (exception ex)
            {
                dapper.rollback();
                //记日志
            }

            //执行删除,有参数,参数可以是实体类、匿名对象、字典(如有需要,可以是集合,以支持批量操作)
            bool deleteresult = dapper.executecommand("delete from t_carinfo where drivername=@drivername", new { drivername = "李四" });

            //构建动态执行sql语句(以下是更新,查询类似)
            stringbuilder updatesqlbuilder = new stringbuilder();
            var updateparams = new dictionary<string, object>();

            if (1 == 1)
            {
                updatesqlbuilder.append(",age=@age");
                updateparams["age"] = 20;
            }

            if (2 == 2)
            {
                updatesqlbuilder.append(",birthday=@birthday");
                updateparams["birthday"] = convert.todatetime("2010-1-1");
            }

            if (3 == 3)
            {
                updatesqlbuilder.append(",homeaddress=@homeaddress");
                updateparams["homeaddress"] = "中国北京天安门";
            }

            string updatesql = string.concat("update t_person set ", updatesqlbuilder.tostring().trimstart(','), "  where  name=@name");
            updateparams["name"] = "张三";

            bool updateresult = dapper.executecommand(updatesql, updateparams);

            //查询返回动态自定义结果,之所以不直接返回dynamic就好,是因为可读性差,故尽可能的在执行后就转成指定的类型
            tuple<string, int> hascarinfo = dapper.getdynamicmodel<tuple<string, int>>((rs) =>
            {
                var result = rs.first();
                return tuple.create<string, int>(result.name, result.carcount);
            }, @"select a.name,count(b.drivername) as carcount from t_person a left join t_carinfo b on a.name=b.drivername where a.name=@name group by a.name", new { name = "张三" });

3.还有两个方法:batchcopydata、batchmovedata,这是特殊封装的,不是基于dapper而是基于原生的ado.net及bcp,目的是快速大量跨db跨表copy数据或转移数据,使用也不复杂,建议想了解的网友可以查看我以往的文章

以上示例方法用到了两个类,如下:

        class person
        {
            public string name { get; set; }


            public int age { get; set; }

            public datetime birthday { get; set; }

            [column(name = "homeaddress")]
            public string homeaddr { get; set; }

            public carinfo car { get; set; }

            public list<carinfo> cars { get; set; }
        }

        class carinfo
        {
            public string brand { get; set; }

            public datetime manufacturedate { get; set; }

            public string drivername { get; set; }
        }

sqldapperutil类中依赖了之前我封装的类:如:memorycacheutil(本地内存依赖缓存实用工具类)、configutil(配置文件管理工具类)、encryptutil(加密工具类),如果项目中不想引用这些类,可以移除或改成其它方法即可。

 另外说明一下,为了防止和减少因db连接未及时释放导致的连接池不足等原因,故默认执行所有的crud方法都是用完即释放,但有一种情况不会释放就是使用了事务,若使用事务,则必需配套使用:usedbtransaction、commit、或失败执行rollback,否则可能导致未能及时释放对象,当然最终当sqldapperutil实例被回收后事务若没有提交或回滚,会强制执行回滚操作并释放事务及连接对象,防止可能的资源浪费情况。

本来早就想总结一下这篇文章,但一直由于工作太忙没有时间,今天利用加班研究.net core的空隙时间完成,请大家支持,有好东西我一定会分享的,虽然不一定高大上,但一定实用且项目中有实战过的。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网