// Internals

        DbCommand CreateCommand(DbCommandDescriptor descriptor)
        {
            var cmd        = _connection.CreateCommand();
            var parameters = descriptor.Parameters;

            if (parameters.Length > 0)
            {
                var paramNames = new string[parameters.Length];

                for (var i = 0; i < parameters.Length; i++)
                {
                    var name = _details.GetParamName(i);
                    paramNames[i] = name;

                    var p = cmd.CreateParameter();
                    p.ParameterName = name;
                    p.Value         = parameters[i] ?? DBNull.Value;
                    cmd.Parameters.Add(p);
                }

                cmd.CommandText = String.Format(descriptor.Sql, paramNames);
            }
            else
            {
                cmd.CommandText = descriptor.Sql;
            }

            if (InTransaction)
            {
                cmd.Transaction = _txStack.Peek();
            }

            return(cmd);
        }
 IEnumerable <T> EnumerateRecords <T>(DbCommandDescriptor descriptor, Func <DbDataReader, T> converter)
 {
     using (var cmd = CreateCommand(descriptor)) {
         QueryWillExecute(cmd);
         using (var reader = cmd.ExecuteReader()) {
             while (reader.Read())
             {
                 yield return(converter(reader));
             }
         }
     }
 }
        T CacheableRead <T>(bool singleCell, bool singleRow, bool useCache, string sql, object[] parameters, Func <DbCommandDescriptor, T> factory)
        {
            var descriptor = new DbCommandDescriptor((singleCell ? 1 : 0) + (singleRow ? 2 : 0), sql, parameters);

            if (useCache && _cache.Contains(descriptor))
            {
                return((T)_cache.Get(descriptor));
            }

            var fresh = factory(descriptor);

            if (useCache)
            {
                _cache.Put(descriptor, fresh);
            }
            else
            {
                _cache.Remove(descriptor);
            }

            return(fresh);
        }
 IDictionary <string, object> Row(DbCommandDescriptor descriptor)
 {
     return(EnumerateRecords(descriptor, RecordToDict).FirstOrDefault());
 }
 T[] Col <T>(DbCommandDescriptor descriptor)
 {
     return(EnumerateRecords(descriptor, GetFirstCellValue <T>).ToArray());
 }
 T Cell <T>(DbCommandDescriptor descriptor)
 {
     return(EnumerateRecords(descriptor, GetFirstCellValue <T>).FirstOrDefault());
 }
 IDictionary <string, object>[] Rows(DbCommandDescriptor descriptor)
 {
     return(EnumerateRecords(descriptor, RecordToDict).ToArray());
 }