private static async Task <IEnumerable <TReturn> > MultiMapAsync <TReturn>(this IDbConnection cnn, CommandDefinition command, Type[] types, Func <object[], TReturn> map, string splitOn)
        {
            if (types.Length < 1)
            {
                throw new ArgumentException("you must provide at least one type to deserialize");
            }

            object param     = command.Parameters;
            var    identity  = new Identity(command.CommandText, command.CommandType, cnn, types[0], param == null ? null : param.GetType(), types);
            var    info      = GetCacheInfo(identity, param, command.AddToCache);
            bool   wasClosed = cnn.State == ConnectionState.Closed;

            try {
                if (wasClosed)
                {
                    await((DbConnection)cnn).OpenAsync().ConfigureAwait(false);
                }
                using (var cmd = (DbCommand)command.SetupCommand(cnn, info.ParamReader))
                    using (var reader = await cmd.ExecuteReaderAsync(command.CancellationToken).ConfigureAwait(false)) {
                        var results = MultiMapImpl <TReturn>(null, default(CommandDefinition), types, map, splitOn, reader, identity, true);
                        return(command.Buffered ? results.ToList() : results);
                    }
            }
            finally {
                if (wasClosed)
                {
                    cnn.Close();
                }
            }
        }
        private static async Task <int> ExecuteImplAsync(IDbConnection cnn, CommandDefinition command, object param)
        {
            var  identity  = new Identity(command.CommandText, command.CommandType, cnn, null, param == null ? null : param.GetType(), null);
            var  info      = GetCacheInfo(identity, param, command.AddToCache);
            bool wasClosed = cnn.State == ConnectionState.Closed;

            using (var cmd = (DbCommand)command.SetupCommand(cnn, info.ParamReader))
            {
                try
                {
                    if (wasClosed)
                    {
                        await((DbConnection)cnn).OpenAsync(command.CancellationToken).ConfigureAwait(false);
                    }
                    var result = await cmd.ExecuteNonQueryAsync(command.CancellationToken).ConfigureAwait(false);

                    command.OnCompleted();
                    return(result);
                }
                finally
                {
                    if (wasClosed)
                    {
                        cnn.Close();
                    }
                }
            }
        }
        private static async Task <IEnumerable <TReturn> > MultiMapAsync <TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(this IDbConnection cnn, CommandDefinition command, Delegate map, string splitOn)
        {
            object param     = command.Parameters;
            var    identity  = new Identity(command.CommandText, command.CommandType, cnn, typeof(TFirst), param == null ? null : param.GetType(), new[] { typeof(TFirst), typeof(TSecond), typeof(TThird), typeof(TFourth), typeof(TFifth), typeof(TSixth), typeof(TSeventh) });
            var    info      = GetCacheInfo(identity, param, command.AddToCache);
            bool   wasClosed = cnn.State == ConnectionState.Closed;

            try
            {
                if (wasClosed)
                {
                    await((DbConnection)cnn).OpenAsync(command.CancellationToken).ConfigureAwait(false);
                }
                using (var cmd = (DbCommand)command.SetupCommand(cnn, info.ParamReader))
                    using (var reader = await cmd.ExecuteReaderAsync(wasClosed ? CommandBehavior.CloseConnection | CommandBehavior.SequentialAccess : CommandBehavior.SequentialAccess, command.CancellationToken).ConfigureAwait(false))
                    {
                        if (!command.Buffered)
                        {
                            wasClosed = false;                // handing back open reader; rely on command-behavior
                        }
                        var results = MultiMapImpl <TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(null, CommandDefinition.ForCallback(command.Parameters), map, splitOn, reader, identity, true);
                        return(command.Buffered ? results.ToList() : results);
                    }
            } finally
            {
                if (wasClosed)
                {
                    cnn.Close();
                }
            }
        }
Exemple #4
0
        /// <summary>
        /// Execute a query asynchronously using .NET 4.5 Task.
        /// </summary>
        public static async Task <IEnumerable <T> > QueryAsync <T>(this IDbConnection cnn, CommandDefinition command)
        {
            object param     = command.Parameters;
            var    identity  = new Identity(command.CommandText, command.CommandType, cnn, typeof(T), param == null ? null : param.GetType(), null);
            var    info      = GetCacheInfo(identity, param);
            bool   wasClosed = cnn.State == ConnectionState.Closed;

            using (var cmd = (DbCommand)command.SetupCommand(cnn, info.ParamReader))
            {
                try
                {
                    if (wasClosed)
                    {
                        await((DbConnection)cnn).OpenAsync().ConfigureAwait(false);
                    }
                    using (var reader = await cmd.ExecuteReaderAsync(command.CancellationToken).ConfigureAwait(false))
                    {
                        return(ExecuteReader <T>(reader, identity, info).ToList());
                    }
                }
                finally
                {
                    if (wasClosed)
                    {
                        cnn.Close();
                    }
                }
            }
        }
        private static async Task <IEnumerable <T> > QueryAsync <T>(this IDbConnection cnn, Type effectiveType, CommandDefinition command)
        {
            object param     = command.Parameters;
            var    identity  = new Identity(command.CommandText, command.CommandType, cnn, effectiveType, param == null ? null : param.GetType(), null);
            var    info      = GetCacheInfo(identity, param, command.AddToCache);
            bool   wasClosed = cnn.State == ConnectionState.Closed;
            var    cancel    = command.CancellationToken;

            using (var cmd = (DbCommand)command.SetupCommand(cnn, info.ParamReader))
            {
                DbDataReader reader = null;
                try
                {
                    if (wasClosed)
                    {
                        await((DbConnection)cnn).OpenAsync(cancel).ConfigureAwait(false);
                    }
                    reader = await cmd.ExecuteReaderAsync(wasClosed?CommandBehavior.CloseConnection | CommandBehavior.SequentialAccess : CommandBehavior.SequentialAccess, cancel).ConfigureAwait(false);

                    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;

                    if (command.Buffered)
                    {
                        List <T> buffer = new List <T>();
                        while (await reader.ReadAsync(cancel).ConfigureAwait(false))
                        {
                            buffer.Add((T)func(reader));
                        }
                        return(buffer);
                    }
                    else
                    {
                        // can't use ReadAsync / cancellation; but this will have to do
                        wasClosed = false; // don't close if handing back an open reader; rely on the command-behavior
                        var deferred = ExecuteReaderSync <T>(reader, func);
                        reader = null;     // to prevent it being disposed before the caller gets to see it
                        return(deferred);
                    }
                }
                finally
                {
                    using (reader) { } // dispose if non-null
                    if (wasClosed)
                    {
                        cnn.Close();
                    }
                }
            }
        }
Exemple #6
0
        private static async Task <IEnumerable <TReturn> > MultiMapAsync <TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(this IDbConnection cnn, CommandDefinition command, Delegate map, string splitOn)
        {
            object param     = command.Parameters;
            var    identity  = new Identity(command.CommandText, command.CommandType, cnn, typeof(TFirst), param == null ? null : param.GetType(), new[] { typeof(TFirst), typeof(TSecond), typeof(TThird), typeof(TFourth), typeof(TFifth), typeof(TSixth), typeof(TSeventh) });
            var    info      = GetCacheInfo(identity);
            bool   wasClosed = cnn.State == ConnectionState.Closed;

            try
            {
                if (wasClosed)
                {
                    await((DbConnection)cnn).OpenAsync();
                }
                using (var cmd = (DbCommand)command.SetupCommand(cnn, info.ParamReader))
                    using (var reader = await cmd.ExecuteReaderAsync(command.CancellationToken))
                    {
                        var results = MultiMapImpl <TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(null, default(CommandDefinition), map, splitOn, reader, identity);
                        return(command.Buffered ? results.ToList() : results);
                    }
            } finally
            {
                if (wasClosed)
                {
                    cnn.Close();
                }
            }
        }
Exemple #7
0
        /// <summary>
        /// Execute a command asynchronously using .NET 4.5 Task.
        /// </summary>
        public static async Task <int> ExecuteAsync(this IDbConnection cnn, CommandDefinition command)
        {
            object param     = command.Parameters;
            var    identity  = new Identity(command.CommandText, command.CommandType, cnn, null, param == null ? null : param.GetType(), null);
            var    info      = GetCacheInfo(identity);
            bool   wasClosed = cnn.State == ConnectionState.Closed;

            using (var cmd = (DbCommand)command.SetupCommand(cnn, info.ParamReader))
            {
                try
                {
                    if (wasClosed)
                    {
                        await((DbConnection)cnn).OpenAsync();
                    }
                    return(await cmd.ExecuteNonQueryAsync(command.CancellationToken));
                }
                finally
                {
                    if (wasClosed)
                    {
                        cnn.Close();
                    }
                }
            }
        }
Exemple #8
0
        private static async Task <IDataReader> ExecuteReaderImplAsync(IDbConnection cnn, CommandDefinition command)
        {
            Action <IDbCommand, object> paramReader = GetParameterReader(cnn, ref command);

            DbCommand cmd       = null;
            bool      wasClosed = cnn.State == ConnectionState.Closed;

            try
            {
                cmd = (DbCommand)command.SetupCommand(cnn, paramReader);
                if (wasClosed)
                {
                    await((DbConnection)cnn).OpenAsync(command.CancellationToken).ConfigureAwait(false);
                }
                var reader = await cmd.ExecuteReaderAsync(wasClosed?CommandBehavior.CloseConnection | CommandBehavior.SequentialAccess : CommandBehavior.SequentialAccess, command.CancellationToken).ConfigureAwait(false);

                wasClosed = false;
                return(reader);
            }
            finally
            {
                if (wasClosed)
                {
                    cnn.Close();
                }
                if (cmd != null)
                {
                    cmd.Dispose();
                }
            }
        }
Exemple #9
0
        /// <summary>
        /// Execute a command that returns multiple result sets, and access each in turn
        /// </summary>
        public static async Task <GridReader> QueryMultipleAsync(this IDbConnection cnn, CommandDefinition command)
        {
            object    param    = command.Parameters;
            Identity  identity = new Identity(command.CommandText, command.CommandType, cnn, typeof(GridReader), param == null ? null : param.GetType(), null);
            CacheInfo info     = GetCacheInfo(identity, param, command.AddToCache);

            DbCommand   cmd       = null;
            IDataReader reader    = null;
            bool        wasClosed = cnn.State == ConnectionState.Closed;

            try
            {
                if (wasClosed)
                {
                    await((DbConnection)cnn).OpenAsync(command.CancellationToken).ConfigureAwait(false);
                }
                cmd    = (DbCommand)command.SetupCommand(cnn, info.ParamReader);
                reader = await cmd.ExecuteReaderAsync(wasClosed?CommandBehavior.CloseConnection | CommandBehavior.SequentialAccess : CommandBehavior.SequentialAccess, command.CancellationToken).ConfigureAwait(false);

                var result = new GridReader(cmd, reader, identity, command.Parameters as DynamicParameters, command.AddToCache, command.CancellationToken);
                wasClosed = false; // *if* the connection was closed and we got this far, then we now have a reader
                // 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
                return(result);
            }
            catch
            {
                if (reader != null)
                {
                    if (!reader.IsClosed)
                    {
                        try
                        { cmd.Cancel(); }
                        catch
                        { /* don't spoil the existing exception */ }
                    }
                    reader.Dispose();
                }
                if (cmd != null)
                {
                    cmd.Dispose();
                }
                if (wasClosed)
                {
                    cnn.Close();
                }
                throw;
            }
        }
Exemple #10
0
        /// <summary>
        /// 查询返回DataSet
        /// </summary>
        /// <param name="cnn"></param>
        /// <param name="adapter"></param>
        /// <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 static DataSet QueryDataSet(this IDbConnection cnn, IDbDataAdapter adapter, string sql, object param = null, IDbTransaction transaction = null, bool buffered = true, int?commandTimeout = null, CommandType?commandType = null)
        {
            var  ds        = new DataSet();
            var  command   = new CommandDefinition(cnn, sql, (object)param, transaction, commandTimeout, commandType, buffered ? CommandFlags.Buffered : CommandFlags.None);
            var  identity  = new Identity(command.CommandText, command.CommandType, cnn, null, param == null ? null : param.GetType(), null);
            var  info      = SqlMapper.GetCacheInfo(identity, param, command.AddToCache);
            bool wasClosed = cnn.State == ConnectionState.Closed;

            if (wasClosed)
            {
                cnn.Open();
            }
            adapter.SelectCommand = command.SetupCommand(cnn, info.ParamReader);
            adapter.Fill(ds);
            if (wasClosed)
            {
                cnn.Close();
            }
            return(ds);
        }
Exemple #11
0
        private async static Task <T> ExecuteScalarImplAsync <T>(IDbConnection cnn, CommandDefinition command)
        {
            Action <IDbCommand, object> paramReader = null;
            object param = command.Parameters;

            if (param != null)
            {
                var identity = new Identity(command.CommandText, command.CommandType, cnn, null, param.GetType(), null);
                paramReader = GetCacheInfo(identity, command.Parameters, command.AddToCache).ParamReader;
            }

            DbCommand cmd       = null;
            bool      wasClosed = cnn.State == ConnectionState.Closed;
            object    result;

            try
            {
                cmd = (DbCommand)command.SetupCommand(cnn, paramReader);
                if (wasClosed)
                {
                    await((DbConnection)cnn).OpenAsync(command.CancellationToken).ConfigureAwait(false);
                }
                result = await cmd.ExecuteScalarAsync(command.CancellationToken).ConfigureAwait(false);

                command.OnCompleted();
            }
            finally
            {
                if (wasClosed)
                {
                    cnn.Close();
                }
                if (cmd != null)
                {
                    cmd.Dispose();
                }
            }
            return(Parse <T>(result));
        }
Exemple #12
0
        /// <summary>
        /// 查询返回DataSet
        /// </summary>
        /// <param name="cnn"></param>
        /// <param name="adapter"></param>
        /// <param name="sql"></param>
        /// <param name="param"></param>
        /// <param name="transaction"></param>
        /// <param name="buffered"></param>
        /// <param name="commandTimeout"></param>
        /// <param name="commandType"></param>
        /// <param name="isExcludeUnitOfWork"></param>
        /// <returns></returns>
        public static async Task <DataSet> QueryDataSetAsync(this IDbConnection cnn, IDbDataAdapter adapter, string sql, object param = null,
                                                             IDbTransaction transaction = null, bool buffered = true, int?commandTimeout = null, CommandType?commandType = null, bool isExcludeUnitOfWork = false)
        {
            var ds      = new DataSet();
            var command = new CommandDefinition(cnn, sql, (object)param, transaction, commandTimeout, commandType,
                                                buffered ? CommandFlags.Buffered : CommandFlags.None, isExcludeUnitOfWork: isExcludeUnitOfWork);
            var  identity  = new Identity(command.CommandText, command.CommandType, cnn, null, param == null ? null : param.GetType(), null);
            var  info      = SqlMapper.GetCacheInfo(identity, param, command.AddToCache);
            bool wasClosed = cnn.State == ConnectionState.Closed;
            var  cancel    = command.CancellationToken;

            if (wasClosed)
            {
                await cnn.TryOpenAsync(cancel).ConfigureAwait(false);
            }
            adapter.SelectCommand = command.SetupCommand(cnn, info.ParamReader);
            adapter.Fill(ds);
            if (wasClosed)
            {
                cnn.Close();
            }
            return(ds);
        }
        private static async Task <int> ExecuteMultiImplAsync(IDbConnection cnn, CommandDefinition command, IEnumerable multiExec)
        {
            bool isFirst   = true;
            int  total     = 0;
            bool wasClosed = cnn.State == ConnectionState.Closed;

            try
            {
                if (wasClosed)
                {
                    await((DbConnection)cnn).OpenAsync(command.CancellationToken).ConfigureAwait(false);
                }

                CacheInfo info      = null;
                string    masterSql = null;
                if ((command.Flags & CommandFlags.Pipelined) != 0)
                {
                    const int MAX_PENDING = 100;
                    var       pending     = new Queue <AsyncExecState>(MAX_PENDING);
                    DbCommand cmd         = null;
                    try
                    {
                        foreach (var obj in multiExec)
                        {
                            if (isFirst)
                            {
                                isFirst   = false;
                                cmd       = (DbCommand)command.SetupCommand(cnn, null);
                                masterSql = cmd.CommandText;
                                var identity = new Identity(command.CommandText, cmd.CommandType, cnn, null, obj.GetType(), null);
                                info = GetCacheInfo(identity, obj, command.AddToCache);
                            }
                            else if (pending.Count >= MAX_PENDING)
                            {
                                var recycled = pending.Dequeue();
                                total += await recycled.Task.ConfigureAwait(false);

                                cmd             = recycled.Command;
                                cmd.CommandText = masterSql; // because we do magic replaces on "in" etc
                                cmd.Parameters.Clear();      // current code is Add-tastic
                            }
                            else
                            {
                                cmd = (DbCommand)command.SetupCommand(cnn, null);
                            }
                            info.ParamReader(cmd, obj);

                            var task = cmd.ExecuteNonQueryAsync(command.CancellationToken);
                            pending.Enqueue(new AsyncExecState(cmd, task));
                            cmd = null; // note the using in the finally: this avoids a double-dispose
                        }
                        while (pending.Count != 0)
                        {
                            var pair = pending.Dequeue();
                            using (pair.Command) { } // dispose commands
                            total += await pair.Task.ConfigureAwait(false);
                        }
                    } finally
                    {
                        // this only has interesting work to do if there are failures
                        using (cmd) { } // dispose commands
                        while (pending.Count != 0)
                        { // dispose tasks even in failure
                            using (pending.Dequeue().Command) { } // dispose commands
                        }
                    }
                }
                else
                {
                    using (var cmd = (DbCommand)command.SetupCommand(cnn, null))
                    {
                        foreach (var obj in multiExec)
                        {
                            if (isFirst)
                            {
                                masterSql = cmd.CommandText;
                                isFirst   = false;
                                var identity = new Identity(command.CommandText, cmd.CommandType, cnn, null, obj.GetType(), null);
                                info = GetCacheInfo(identity, obj, command.AddToCache);
                            }
                            else
                            {
                                cmd.CommandText = masterSql; // because we do magic replaces on "in" etc
                                cmd.Parameters.Clear();      // current code is Add-tastic
                            }
                            info.ParamReader(cmd, obj);
                            total += await cmd.ExecuteNonQueryAsync(command.CancellationToken).ConfigureAwait(false);
                        }
                    }
                }

                command.OnCompleted();
            }
            finally
            {
                if (wasClosed)
                {
                    cnn.Close();
                }
            }
            return(total);
        }
Exemple #14
0
        private static async Task <T> QueryFirstOrDefaultAsync <T>(this IDbConnection cnn, Type effectiveType, CommandDefinition command)
        {
            object param     = command.Parameters;
            var    identity  = new Identity(command.CommandText, command.CommandType, cnn, effectiveType, param?.GetType(), null);
            var    info      = GetCacheInfo(identity, param, command.AddToCache);
            bool   wasClosed = cnn.State == ConnectionState.Closed;
            var    cancel    = command.CancellationToken;

            using (var cmd = (DbCommand)command.SetupCommand(cnn, info.ParamReader))
            {
                DbDataReader reader = null;
                try
                {
                    if (wasClosed)
                    {
                        await((DbConnection)cnn).OpenAsync(cancel).ConfigureAwait(false);
                    }
                    reader = await cmd.ExecuteReaderAsync(wasClosed?CommandBehavior.CloseConnection | CommandBehavior.SequentialAccess : CommandBehavior.SequentialAccess, cancel).ConfigureAwait(false);

                    T result = default(T);
                    if (await reader.ReadAsync(cancel).ConfigureAwait(false))
                    {
                        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);
                        }
                        while (await reader.ReadAsync(cancel).ConfigureAwait(false))
                        {
                        }
                    }
                    while (await reader.NextResultAsync(cancel).ConfigureAwait(false))
                    {
                    }
                    return(result);
                }
                finally
                {
                    using (reader) { } // dispose if non-null
                    if (wasClosed)
                    {
                        cnn.Close();
                    }
                }
            }
        }