Dapper记录

日常记录,Dapper(ORM框架)的封装

public static class DBContext
    {
        private static IDbConnection _dbConnection = new MySqlConnection();
        public static string ConnectionString { get; set; }

        public static IDbConnection dbConnection
        {
            get
            {
                if (!string.IsNullOrEmpty(ConnectionString) && string.IsNullOrEmpty(_dbConnection.ConnectionString))
                {
                    _dbConnection.ConnectionString = ConnectionString;
                }
                return _dbConnection;
            }
        }

        public static void AddDbContext(this IServiceCollection service, string connectionString)
        {
            ConnectionString = connectionString;
            service.AddScoped<IDapperHelper,DapperHelper> ();
        }

    }
public interface IDapperHelper
    {
        /// <summary>
        /// 查询一条数据
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="sql">sql语句</param>
        /// <param name="param">参数</param>
        /// <param name="commandTimeout">查询超时时间</param>
        /// <param name="commandType">sql语句类型</param>
        /// <param name="transaction">事务</param>
        /// <returns></returns>
        T QueryFirst<T>
            (
                string sql,
                object param,
                IDbTransaction transaction = null,
                int? commandTimeout = null,
                CommandType commandType = CommandType.Text
            ) where T : class;
         

        /// <summary>
        /// 查询所有数据
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="sql">sql语句</param>
        /// <param name="param">参数</param>
        /// <param name="buffered">是否缓存查询结果</param>
        /// <param name="commandTimeout">查询超时时间</param>
        /// <param name="commandType">sql语句类型</param>
        /// <param name="transaction">事务</param>
        /// <returns></returns>
        IEnumerable<T> Query<T>(
                string sql,
                object param,
                IDbTransaction transaction = null,
                bool buffered = true,
                int? commandTimeout = null,
                CommandType commandType = CommandType.Text
            ) where T : class;


        /// <summary>
        /// 执行sql
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <param name="transaction"></param>
        /// <param name="commandTimeout"></param>
        /// <param name="commandType"></param>
        /// <returns></returns>
        int Execute(
                string sql,
                object param,
                IDbTransaction transaction = null,
                int? commandTimeout = null,
                CommandType commandType = CommandType.Text
            );
        
    }
public class DapperHelper : IDapperHelper
    {
        //private IDbConnection _dbConnection = new MySqlConnection();

        //private string ConnectionString => DBContext.ConnectionString;
        //public DapperHelper()
        //{
        //    _dbConnection.ConnectionString = ConnectionString;
        //}
        /// <summary>
        /// 查询一条数据
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="sql">sql语句</param>
        /// <param name="param">参数</param>
        /// <param name="commandTimeout">查询超时时间</param>
        /// <param name="commandType">sql语句类型</param>
        /// <param name="transaction">事务</param>
        /// <returns></returns>
        public T QueryFirst<T>
            (
                string sql,
                object param,
                IDbTransaction transaction = null,
                int? commandTimeout = null,
                CommandType commandType = CommandType.Text
            ) where T : class
        {
            if (DBContext.dbConnection.State != ConnectionState.Open)
            {
                DBContext.dbConnection.Open();
            }
            using (transaction = DBContext.dbConnection.BeginTransaction())
            { 
                var res = DBContext.dbConnection.QueryFirstOrDefault<T>(sql, param, transaction, commandTimeout, commandType);
                transaction.Commit();
                //DBContext.dbConnection.Close();
                return res;
            }
        }

        /// <summary>
        /// 查询所有数据
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="sql">sql语句</param>
        /// <param name="param">参数</param>
        /// <param name="buffered">是否缓存查询结果</param>
        /// <param name="commandTimeout">查询超时时间</param>
        /// <param name="commandType">sql语句类型</param>
        /// <param name="transaction">事务</param>
        /// <returns></returns>
        public IEnumerable<T> Query<T>(
                string sql,
                object param,
                IDbTransaction transaction = null,
                bool buffered = true,
                int? commandTimeout = null,
                CommandType commandType = CommandType.Text
            ) where T : class
        { 
            return DBContext.dbConnection.Query<T>(sql, param, transaction, buffered, commandTimeout, commandType);
        }

        /// <summary>
        /// 执行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 int Execute(
                string sql,
                object param,
                IDbTransaction transaction = null,
                int? commandTimeout = null,
                CommandType commandType = CommandType.Text
            )
        { 
            return DBContext.dbConnection.Execute(sql, param, transaction, commandTimeout, commandType);
        }

    }

---dapperExt

public interface IDbExtDapperHelper<T> where T : BaseModel, new()
    {
        IEnumerable<T> GetAll();
        T GetT(T t);
        bool Insert(T t);
        bool Update(T t);
    }
public class DbExtDapperHelper<T> : IDbExtDapperHelper<T> where T : BaseModel, new()
    {
        private IDbConnection dbConnection
        {
            get
            {
                return DBContext.dbConnection;
            }
        }

        public T GetT(T t)
        {
            return dbConnection.Get<T>(t);
        }
        public IEnumerable<T> GetAll()
        {
            var res = dbConnection.GetAll<T>();
            return res;
        }
        public bool Update(T t)
        {
            //var tt = Activator.CreateInstance(typeof(Users));
            return dbConnection.Update<T>(t);
        }
         
        public bool Insert(T t)
        {
            return dbConnection.Insert<T>(t) > 0;
        }
    }

--startup.cs中注入

 services.AddDbContext(Configuration.GetConnectionString("MysqlConnectionString"));
 services.AddScoped<UserDAL>();
 services.AddScoped(typeof(IDbExtDapperHelper<>),typeof(DbExtDapperHelper<>));//泛型注入

--dapperext的特性扩展

    [Table("users")]
    public class Users : BaseModel
    {
        public string Password { get; set; }
        public string UserName { get; set; }
        public int? UserLevel { get; set; }
        public int? IsDelete { get; set; }
    }

自己的一些笔记

dapper的一个源码:

private static T QueryRowImpl<T>(IDbConnection cnn, Row row, ref CommandDefinition command, Type effectiveType)
        {
            object param = command.Parameters;
            var identity = new Identity(command.CommandText, command.CommandType, cnn, effectiveType, param?.GetType(), null);
            var info = GetCacheInfo(identity, param, command.AddToCache);

            IDbCommand cmd = null;
            IDataReader reader = null;

            bool wasClosed = cnn.State == ConnectionState.Closed;
            try
            {
                cmd = command.SetupCommand(cnn, info.ParamReader);

                if (wasClosed) cnn.Open();//如果使用事务,前面使用时Conn需要打开,dapper没有帮你打开。基础先判断后打开。。
                reader = ExecuteReaderWithFlagsFallback(cmd, wasClosed, (row & Row.Single) != 0
                    ? CommandBehavior.SequentialAccess | CommandBehavior.SingleResult // need to allow multiple rows, to check fail condition
                    : CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow);
                wasClosed = false; // *if* the connection was closed and we got this far, then we now have a reader

                T result = default(T);
                if (reader.Read() && reader.FieldCount != 0)
                {
                    // with the CloseConnection flag, so the reader will deal with the connection; we
                    // still need something in the "finally" to ensure that broken SQL still results
                    // in the connection closing itself
                    var tuple = info.Deserializer;
                    int hash = GetColumnHash(reader);
                    if (tuple.Func == null || tuple.Hash != hash)
                    {
                        tuple = info.Deserializer = new DeserializerState(hash, GetDeserializer(effectiveType, reader, 0, -1, false));
                        if (command.AddToCache) SetQueryCache(identity, info);
                    }

                    var func = tuple.Func;
                    object val = func(reader);
                    if (val == null || val is T)
                    {
                        result = (T)val;
                    }
                    else
                    {
                        var convertToType = Nullable.GetUnderlyingType(effectiveType) ?? effectiveType;
                        result = (T)Convert.ChangeType(val, convertToType, CultureInfo.InvariantCulture);
                    }
                    if ((row & Row.Single) != 0 && reader.Read()) ThrowMultipleRows(row);
                    while (reader.Read()) { }
                }
                else if ((row & Row.FirstOrDefault) == 0) // demanding a row, and don't have one
                {
                    ThrowZeroRows(row);
                }
                while (reader.NextResult()) { }
                // happy path; close the reader cleanly - no
                // need for "Cancel" etc
                reader.Dispose();
                reader = null;

                command.OnCompleted();
                return result;
            }
            finally
            {
                if (reader != null)
                {
                    if (!reader.IsClosed) try { cmd.Cancel(); }
                        catch { /* don't spoil the existing exception */ }
                    reader.Dispose();
                }
                if (wasClosed) cnn.Close();
                cmd?.Dispose();
            }
        }

--dapper.controb的一个扩展源码

        /// <summary>
        /// Returns a single entity by a single id from table "Ts".  
        /// Id must be marked with [Key] attribute.
        /// Entities created from interfaces are tracked/intercepted for changes and used by the Update() extension
        /// for optimal performance. 
        /// </summary>
        /// <typeparam name="T">Interface or type to create and populate</typeparam>
        /// <param name="connection">Open SqlConnection</param>
        /// <param name="id">Id of the entity to get, must be marked with [Key] attribute</param>
        /// <param name="transaction">The transaction to run under, null (the default) if none</param>
        /// <param name="commandTimeout">Number of seconds before command execution timeout</param>
        /// <returns>Entity of T</returns>
        public static T Get<T>(this IDbConnection connection, dynamic id, IDbTransaction transaction = null, int? commandTimeout = null) where T : class
        {
            var type = typeof(T);

            string sql;
            if (!GetQueries.TryGetValue(type.TypeHandle, out sql))
            {
                var key = GetSingleKey<T>(nameof(Get));
                var name = GetTableName(type);

                sql = $"select * from {name} where {key.Name} = @id";//组装成sql,调用dapper基础使用方法
                GetQueries[type.TypeHandle] = sql;
            }

            var dynParms = new DynamicParameters();
            dynParms.Add("@id", id);

            T obj;

            if (type.IsInterface())
            {
                var res = connection.Query(sql, dynParms).FirstOrDefault() as IDictionary<string, object>;

                if (res == null)
                    return null;

                obj = ProxyGenerator.GetInterfaceProxy<T>();

                foreach (var property in TypePropertiesCache(type))
                {
                    var val = res[property.Name];
                    property.SetValue(obj, Convert.ChangeType(val, property.PropertyType), null);
                }

                ((IProxy)obj).IsDirty = false;   //reset change tracking and return
            }
            else
            {
                obj = connection.Query<T>(sql, dynParms, transaction, commandTimeout: commandTimeout).FirstOrDefault();
            }
            return obj;
        }

 

---其他记录

Dapper---
轻量级==?简单。


1.Dapper
  Dapper.Contrib(扩展T)
  MySqlClient(对mySql的支持)
2.C# 连接Mysql 字符串
Database=bbs;Data Source=127.0.0.1;User Id=root;Password=root;pooling=false;CharSet=utf8;port=3306


3.设施层进化思路:
 1)在哪里,什么时候获取ConnectionString,
 2)静态实例,属性获取这个静态实例(get时给这个静态实例加属性,如连接字符串)。单例模式。
 3)IServiceCollection扩展下,注入到startup.cs中。
4.配置连接字符串mysql
  "ConnectionStrings": {
    "MysqlConnectionString": "Database=bbs;Data Source=localhost;User Id=root;Password=root;port=3306;SslMode=none;"
  },
5.写dbhelper
public static class DBContext
    {
        private static IDbConnection _dbConnection = new MySqlConnection();
        public static string ConnectionString { get; set; }

        public static IDbConnection dbConnection
        {
            get
            {
               if (!string.IsNullOrEmpty(ConnectionString) && string.IsNullOrEmpty(_dbConnection.ConnectionString))
                {
                    _dbConnection.ConnectionString = ConnectionString;
                }
                return _dbConnection;
            }
        }

        public static void AddDbContext(this IServiceCollection service, string connectionString)
        {
            ConnectionString = connectionString;
            service.AddScoped<IDapperHelper,DapperHelper> ();
        }

    }
-----------
public interface IDapperHelper
    {
 
        T QueryFirst<T>
            (
                string sql,
                object param,
                IDbTransaction transaction = null,
                int? commandTimeout = null,
                CommandType commandType = CommandType.Text
            ) where T : class;
         
        IEnumerable<T> Query<T>(
                string sql,
                object param,
                IDbTransaction transaction = null,
                bool buffered = true,
                int? commandTimeout = null,
                CommandType commandType = CommandType.Text
            ) where T : class;
 
        int Execute(
                string sql,
                object param,
                IDbTransaction transaction = null,
                int? commandTimeout = null,
                CommandType commandType = CommandType.Text
            );
        
    }
 ------
 public class DapperHelper : IDapperHelper
    {
        //private IDbConnection _dbConnection = new MySqlConnection();
        //
        //private string ConnectionString => DBContext.ConnectionString;
        //public DapperHelper()
        //{
        //    _dbConnection.ConnectionString = ConnectionString;
        //}
        
        /// <summary>
        /// 查询一条数据
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="sql">sql语句</param>
        /// <param name="param">参数</param>
        /// <param name="commandTimeout">查询超时时间</param>
        /// <param name="commandType">sql语句类型</param>
        /// <param name="transaction">事务</param>
        /// <returns></returns>
        public T QueryFirst<T>
            (
                string sql,
                object param,
                IDbTransaction transaction = null,
                int? commandTimeout = null,
                CommandType commandType = CommandType.Text
            ) where T : class
        {
            if (DBContext.dbConnection.State != ConnectionState.Open)//这里我也忘了。。
            {
                DBContext.dbConnection.Open();
            }
            using (transaction = DBContext.dbConnection.BeginTransaction())
            { 
                var res = DBContext.dbConnection.QueryFirstOrDefault<T>(sql, param, transaction, commandTimeout, commandType);
                transaction.Commit();
                DBContext.dbConnection.Close();
                return res;
            }
        }

        /// <summary>
        /// 查询所有数据
        /// </summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="sql">sql语句</param>
        /// <param name="param">参数</param>
        /// <param name="buffered">是否缓存查询结果</param>
        /// <param name="commandTimeout">查询超时时间</param>
        /// <param name="commandType">sql语句类型</param>
        /// <param name="transaction">事务</param>
        /// <returns></returns>
        public IEnumerable<T> Query<T>(
                string sql,
                object param,
                IDbTransaction transaction = null,
                bool buffered = true,
                int? commandTimeout = null,
                CommandType commandType = CommandType.Text
            ) where T : class
        { 
            return DBContext.dbConnection.Query<T>(sql, param, transaction, buffered, commandTimeout, commandType);
        }

        /// <summary>
        /// 执行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 int Execute(
                string sql,
                object param,
                IDbTransaction transaction = null,
                int? commandTimeout = null,
                CommandType commandType = CommandType.Text
            )
        { 
            return DBContext.dbConnection.Execute(sql, param, transaction, commandTimeout, commandType);
        }
    }
6,startup.cs中:
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext(Configuration.GetConnectionString("MysqlConnectionString"));
    services.AddScoped<UserDAL>();
    
}
7,controller中使用:
 public class UsersController : ControllerBase
{
    private readonly UserDAL _userDAL = null;
    public UsersController(UserDAL userDAL)
    {
        _userDAL = userDAL;
    }

    [HttpGet("UserName/Password")]
    public Users Get(string UserName,string Password)
    {
        return _userDAL.GetUserByLogin(UserName,Password);
    }
}
 
----注入模式记录。。
AddTransient瞬时模式:每次请求,都获取一个新的实例。即使同一个请求获取多次也会是不同的实例
AddScoped:每次请求,都获取一个新的实例。同一个请求获取多次会得到相同的实例
AddSingleton单例模式:每次都获取同一个实例


--Dapper源码解读:
        /// <summary>
        /// Executes a single-row query, returning the data typed as per T
        /// </summary>
        /// <returns>A sequence of data of the supplied type; if a basic type (int, string, etc) is queried then the data from the first column in assumed, otherwise an instance is
        /// created per row, and a direct column-name===member-name mapping is assumed (case insensitive).
        /// </returns>
        public static T QuerySingle<T>(
            this IDbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null
        )
        {
            var command = new CommandDefinition(sql, param, transaction, commandTimeout, commandType, CommandFlags.None);
            return QueryRowImpl<T>(cnn, Row.Single, ref command, typeof(T));
        }
--
 /// <summary>
        /// Initialize the command definition--给私有化变量赋值
        /// </summary>
        public CommandDefinition(string commandText, object parameters = null, IDbTransaction transaction = null, int? commandTimeout = null,
                                 CommandType? commandType = null, CommandFlags flags = CommandFlags.Buffered
#if ASYNC
                                 , CancellationToken cancellationToken = default(CancellationToken)
#endif
            )
        {
            CommandText = commandText;
            Parameters = parameters;
            Transaction = transaction;
            CommandTimeout = commandTimeout;
            CommandType = commandType;
            Flags = flags;
#if ASYNC
            CancellationToken = cancellationToken;
#endif
        }
-----
      private static T QueryRowImpl<T>(IDbConnection cnn, Row row, ref CommandDefinition command, Type effectiveType)
        {
            object param = command.Parameters;
            var identity = new Identity(command.CommandText, command.CommandType, cnn, effectiveType, param?.GetType(), null);
            var info = GetCacheInfo(identity, param, command.AddToCache);

            IDbCommand cmd = null;
            IDataReader reader = null;

            bool wasClosed = cnn.State == ConnectionState.Closed;
            try
            {
                cmd = command.SetupCommand(cnn, info.ParamReader);

                if (wasClosed) cnn.Open();
                reader = ExecuteReaderWithFlagsFallback(cmd, wasClosed, (row & Row.Single) != 0
                    ? CommandBehavior.SequentialAccess | CommandBehavior.SingleResult // need to allow multiple rows, to check fail condition
                    : CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow);
                wasClosed = false; // *if* the connection was closed and we got this far, then we now have a reader

                T result = default(T);
                if (reader.Read() && reader.FieldCount != 0)
                {
                    // with the CloseConnection flag, so the reader will deal with the connection; we
                    // still need something in the "finally" to ensure that broken SQL still results
                    // in the connection closing itself
                    var tuple = info.Deserializer;
                    int hash = GetColumnHash(reader);
                    if (tuple.Func == null || tuple.Hash != hash)
                    {
                        tuple = info.Deserializer = new DeserializerState(hash, GetDeserializer(effectiveType, reader, 0, -1, false));
                        if (command.AddToCache) SetQueryCache(identity, info);
                    }

                    var func = tuple.Func;
                    object val = func(reader);
                    if (val == null || val is T)
                    {
                        result = (T)val;
                    }
                    else
                    {
                        var convertToType = Nullable.GetUnderlyingType(effectiveType) ?? effectiveType;
                        result = (T)Convert.ChangeType(val, convertToType, CultureInfo.InvariantCulture);
                    }
                    if ((row & Row.Single) != 0 && reader.Read()) ThrowMultipleRows(row);
                    while (reader.Read()) { }
                }
                else if ((row & Row.FirstOrDefault) == 0) // demanding a row, and don't have one
                {
                    ThrowZeroRows(row);
                }
                while (reader.NextResult()) { }
                // happy path; close the reader cleanly - no
                // need for "Cancel" etc
                reader.Dispose();
                reader = null;

                command.OnCompleted();
                return result;
            }
            finally
            {
                if (reader != null)
                {
                    if (!reader.IsClosed) try { cmd.Cancel(); }
                        catch { /* don't spoil the existing exception */ }
                    reader.Dispose();
                }
                if (wasClosed) cnn.Close();
                cmd?.Dispose();
            }
        }
        
        
        
        

 

posted @ 2021-09-14 16:07  vba是最好的语言  阅读(114)  评论(0编辑  收藏  举报