Commit 12886d80 authored by Nick Craver's avatar Nick Craver

Merge pull request #391 from henkmollema/code-cleanup2

Code cleanup - take 2
parents 295d1ad2 c28a87ff
......@@ -18,9 +18,10 @@
#endif
namespace Dapper
{ /// <summary>
/// Represents the key aspects of a sql operation
/// </summary>
{
/// <summary>
/// Represents the key aspects of a sql operation
/// </summary>
public struct CommandDefinition
{
internal static CommandDefinition ForCallback(object parameters)
......@@ -34,125 +35,119 @@ internal static CommandDefinition ForCallback(object parameters)
return default(CommandDefinition);
}
}
private readonly string commandText;
private readonly object parameters;
private readonly IDbTransaction transaction;
private readonly int? commandTimeout;
private readonly CommandType? commandType;
private readonly CommandFlags flags;
internal void OnCompleted()
{
if (parameters is SqlMapper.IParameterCallbacks)
{
((SqlMapper.IParameterCallbacks)parameters).OnCompleted();
}
(Parameters as SqlMapper.IParameterCallbacks)?.OnCompleted();
}
/// <summary>
/// The command (sql or a stored-procedure name) to execute
/// </summary>
public string CommandText { get { return commandText; } }
public string CommandText { get; }
/// <summary>
/// The parameters associated with the command
/// </summary>
public object Parameters { get { return parameters; } }
public object Parameters { get; }
/// <summary>
/// The active transaction for the command
/// </summary>
public IDbTransaction Transaction { get { return transaction; } }
public IDbTransaction Transaction { get; }
/// <summary>
/// The effective timeout for the command
/// </summary>
public int? CommandTimeout { get { return commandTimeout; } }
public int? CommandTimeout { get; }
/// <summary>
/// The type of command that the command-text represents
/// </summary>
public CommandType? CommandType { get { return commandType; } }
public CommandType? CommandType { get; }
/// <summary>
/// Should data be buffered before returning?
/// </summary>
public bool Buffered { get { return (flags & CommandFlags.Buffered) != 0; } }
public bool Buffered => (Flags & CommandFlags.Buffered) != 0;
/// <summary>
/// Should the plan for this query be cached?
/// </summary>
internal bool AddToCache { get { return (flags & CommandFlags.NoCache) == 0; } }
internal bool AddToCache => (Flags & CommandFlags.NoCache) == 0;
/// <summary>
/// Additional state flags against this command
/// </summary>
public CommandFlags Flags { get { return flags; } }
public CommandFlags Flags { get; }
/// <summary>
/// Can async queries be pipelined?
/// </summary>
public bool Pipelined { get { return (flags & CommandFlags.Pipelined) != 0; } }
public bool Pipelined => (Flags & CommandFlags.Pipelined) != 0;
/// <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
CommandType? commandType = null, CommandFlags flags = CommandFlags.Buffered
#if ASYNC
, CancellationToken cancellationToken = default(CancellationToken)
, CancellationToken cancellationToken = default(CancellationToken)
#endif
)
{
this.commandText = commandText;
this.parameters = parameters;
this.transaction = transaction;
this.commandTimeout = commandTimeout;
this.commandType = commandType;
this.flags = flags;
CommandText = commandText;
Parameters = parameters;
Transaction = transaction;
CommandTimeout = commandTimeout;
CommandType = commandType;
Flags = flags;
#if ASYNC
this.cancellationToken = cancellationToken;
CancellationToken = cancellationToken;
#endif
}
private CommandDefinition(object parameters) : this()
{
this.parameters = parameters;
Parameters = parameters;
}
#if ASYNC
private readonly CancellationToken cancellationToken;
/// <summary>
/// For asynchronous operations, the cancellation-token
/// </summary>
public CancellationToken CancellationToken { get { return cancellationToken; } }
public CancellationToken CancellationToken { get; }
#endif
internal IDbCommand SetupCommand(IDbConnection cnn, Action<IDbCommand, object> paramReader)
{
var cmd = cnn.CreateCommand();
var init = GetInit(cmd.GetType());
if (init != null) init(cmd);
if (transaction != null)
cmd.Transaction = transaction;
cmd.CommandText = commandText;
if (commandTimeout.HasValue)
init?.Invoke(cmd);
if (Transaction != null)
cmd.Transaction = Transaction;
cmd.CommandText = CommandText;
if (CommandTimeout.HasValue)
{
cmd.CommandTimeout = commandTimeout.Value;
cmd.CommandTimeout = CommandTimeout.Value;
}
else if (SqlMapper.Settings.CommandTimeout.HasValue)
{
cmd.CommandTimeout = SqlMapper.Settings.CommandTimeout.Value;
}
if (commandType.HasValue)
cmd.CommandType = commandType.Value;
if (paramReader != null)
{
paramReader(cmd, parameters);
}
if (CommandType.HasValue)
cmd.CommandType = CommandType.Value;
paramReader?.Invoke(cmd, Parameters);
return cmd;
}
static SqlMapper.Link<Type, Action<IDbCommand>> commandInitCache;
static Action<IDbCommand> GetInit(Type commandType)
private static SqlMapper.Link<Type, Action<IDbCommand>> commandInitCache;
private static Action<IDbCommand> GetInit(Type commandType)
{
if (commandType == null) return null; // GIGO
if (commandType == null)
return null; // GIGO
Action<IDbCommand> action;
if (SqlMapper.Link<Type, Action<IDbCommand>>.TryGet(commandInitCache, commandType, out action))
{
......@@ -186,11 +181,12 @@ static Action<IDbCommand> GetInit(Type commandType)
il.Emit(OpCodes.Ret);
action = (Action<IDbCommand>)method.CreateDelegate(typeof(Action<IDbCommand>));
}
// cache it
// cache it
SqlMapper.Link<Type, Action<IDbCommand>>.TryAdd(ref commandInitCache, commandType, ref action);
return action;
}
static MethodInfo GetBasicPropertySetter(Type declaringType, string name, Type expectedType)
private static MethodInfo GetBasicPropertySetter(Type declaringType, string name, Type expectedType)
{
var prop = declaringType.GetProperty(name, BindingFlags.Public | BindingFlags.Instance);
ParameterInfo[] indexers;
......
......@@ -20,10 +20,10 @@ public sealed class CustomPropertyTypeMap : SqlMapper.ITypeMap
public CustomPropertyTypeMap(Type type, Func<Type, string, PropertyInfo> propertySelector)
{
if (type == null)
throw new ArgumentNullException("type");
throw new ArgumentNullException(nameof(type));
if (propertySelector == null)
throw new ArgumentNullException("propertySelector");
throw new ArgumentNullException(nameof(propertySelector));
_type = type;
_propertySelector = propertySelector;
......
......@@ -3,7 +3,7 @@
#if !DNXCORE50
namespace Dapper
{
sealed class DataTableHandler : Dapper.SqlMapper.ITypeHandler
sealed class DataTableHandler : SqlMapper.ITypeHandler
{
public object Parse(Type destinationType, object value)
{
......
......@@ -19,7 +19,7 @@ namespace Dapper
/// <summary>
/// This class represents a SQL string, it can be used if you need to denote your parameter is a Char vs VarChar vs nVarChar vs nChar
/// </summary>
public sealed class DbString : Dapper.SqlMapper.ICustomQueryParameter
public sealed class DbString : SqlMapper.ICustomQueryParameter
{
/// <summary>
/// Default value for IsAnsi.
......
......@@ -11,7 +11,6 @@ namespace Dapper
sealed class DefaultTypeMap : SqlMapper.ITypeMap
{
private readonly List<FieldInfo> _fields;
private readonly List<PropertyInfo> _properties;
private readonly Type _type;
/// <summary>
......@@ -21,10 +20,10 @@ sealed class DefaultTypeMap : SqlMapper.ITypeMap
public DefaultTypeMap(Type type)
{
if (type == null)
throw new ArgumentNullException("type");
throw new ArgumentNullException(nameof(type));
_fields = GetSettableFields(type);
_properties = GetSettableProps(type);
Properties = GetSettableProps(type);
_type = type;
}
#if DNXCORE50
......@@ -184,12 +183,6 @@ public SqlMapper.IMemberMap GetMember(string columnName)
/// </summary>
public static bool MatchNamesWithUnderscores { get; set; }
public List<PropertyInfo> Properties
{
get
{
return _properties;
}
}
public List<PropertyInfo> Properties { get; }
}
}
......@@ -198,7 +198,7 @@ protected void AddParameters(IDbCommand command, SqlMapper.Identity identity)
appender(command, template);
}
// The parameters were added to the command, but not the
// The parameters were added to the command, but not the
// DynamicParameters until now.
foreach (IDbDataParameter param in command.Parameters)
{
......@@ -246,7 +246,7 @@ protected void AddParameters(IDbCommand command, SqlMapper.Identity identity)
{
((SqlMapper.ICustomQueryParameter)val).AddParameter(command, name);
}
else if (dbType == DynamicParameters.EnumerableMultiParameter)
else if (dbType == EnumerableMultiParameter)
{
#pragma warning disable 612, 618
SqlMapper.PackListParameters(command, name, val);
......@@ -276,12 +276,9 @@ protected void AddParameters(IDbCommand command, SqlMapper.Identity identity)
p.DbType = dbType.Value;
}
var s = val as string;
if (s != null)
if (s?.Length <= DbString.DefaultLength)
{
if (s.Length <= DbString.DefaultLength)
{
p.Size = DbString.DefaultLength;
}
p.Size = DbString.DefaultLength;
}
if (param.Size != null) p.Size = param.Size.Value;
if (param.Precision != null) p.Precision = param.Precision.Value;
......@@ -344,7 +341,7 @@ public T Get<T>(string name)
/// <summary>
/// Allows you to automatically populate a target property/field from output parameters. It actually
/// creates an InputOutput parameter, so you can still pass data in.
/// creates an InputOutput parameter, so you can still pass data in.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="target">The object whose property/field you wish to populate.</param>
......@@ -383,13 +380,13 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express
do
{
// Insert the names in the right order so expression
// Insert the names in the right order so expression
// "Post.Author.Name" becomes parameter "PostAuthorName"
names.Insert(0, diving.Member.Name);
names.Insert(0, diving?.Member.Name);
chain.Insert(0, diving);
var constant = diving.Expression as ParameterExpression;
diving = diving.Expression as MemberExpression;
var constant = diving?.Expression as ParameterExpression;
diving = diving?.Expression as MemberExpression;
if (constant != null &&
constant.Type == typeof(T))
......@@ -423,7 +420,7 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express
if (setter != null) goto MAKECALLBACK;
// Come on let's build a method, let's build it, let's build it now!
var dm = new DynamicMethod(string.Format("ExpressionParam{0}", Guid.NewGuid()), null, new[] { typeof(object), this.GetType() }, true);
var dm = new DynamicMethod($"ExpressionParam{Guid.NewGuid()}", null, new[] { typeof(object), GetType() }, true);
var il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0); // [object]
......@@ -446,7 +443,7 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express
}
}
var paramGetter = this.GetType().GetMethod("Get", new Type[] { typeof(string) }).MakeGenericMethod(lastMemberAccess.Type);
var paramGetter = GetType().GetMethod("Get", new Type[] { typeof(string) }).MakeGenericMethod(lastMemberAccess.Type);
il.Emit(OpCodes.Ldarg_1); // [target] [DynamicParameters]
il.Emit(OpCodes.Ldstr, dynamicParamName); // [target] [DynamicParameters] [ParamName]
......@@ -478,10 +475,10 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express
{
// Finally, prep the parameter and attach the callback to it
ParamInfo parameter;
var targetMemberType = lastMemberAccess.Type;
var targetMemberType = lastMemberAccess?.Type;
int sizeToSet = (!size.HasValue && targetMemberType == typeof(string)) ? DbString.DefaultLength : size ?? 0;
if (this.parameters.TryGetValue(dynamicParamName, out parameter))
if (parameters.TryGetValue(dynamicParamName, out parameter))
{
parameter.ParameterDirection = parameter.AttachedParam.Direction = ParameterDirection.InputOutput;
......@@ -493,14 +490,14 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express
else
{
SqlMapper.ITypeHandler handler;
dbType = (!dbType.HasValue) ? SqlMapper.LookupDbType(targetMemberType, targetMemberType.Name, true, out handler) : dbType;
dbType = (!dbType.HasValue) ? SqlMapper.LookupDbType(targetMemberType, targetMemberType?.Name, true, out handler) : dbType;
// CameFromTemplate property would not apply here because this new param
// Still needs to be added to the command
this.Add(dynamicParamName, expression.Compile().Invoke(target), null, ParameterDirection.InputOutput, sizeToSet);
Add(dynamicParamName, expression.Compile().Invoke(target), null, ParameterDirection.InputOutput, sizeToSet);
}
parameter = this.parameters[dynamicParamName];
parameter = parameters[dynamicParamName];
parameter.OutputCallback = setter;
parameter.OutputTarget = target;
});
......@@ -518,7 +515,7 @@ void SqlMapper.IParameterCallbacks.OnCompleted()
{
foreach (var param in (from p in parameters select p.Value))
{
if (param.OutputCallback != null) param.OutputCallback(param.OutputTarget, this);
param.OutputCallback?.Invoke(param.OutputTarget, this);
}
}
}
......
......@@ -28,7 +28,7 @@ private static readonly FeatureSupport
/// </summary>
public static FeatureSupport Get(IDbConnection connection)
{
string name = connection == null ? null : connection.GetType().Name;
string name = connection?.GetType().Name;
if (string.Equals(name, "npgsqlconnection", StringComparison.OrdinalIgnoreCase)) return postgres;
return @default;
}
......@@ -39,7 +39,7 @@ private FeatureSupport(bool arrays)
/// <summary>
/// True if the db supports array columns e.g. Postgresql
/// </summary>
public bool Arrays { get; private set; }
public bool Arrays { get; }
}
}
......@@ -8,11 +8,6 @@ namespace Dapper
/// </summary>
sealed class SimpleMemberMap : SqlMapper.IMemberMap
{
private readonly string _columnName;
private readonly PropertyInfo _property;
private readonly FieldInfo _field;
private readonly ParameterInfo _parameter;
/// <summary>
/// Creates instance for simple property mapping
/// </summary>
......@@ -21,13 +16,13 @@ sealed class SimpleMemberMap : SqlMapper.IMemberMap
public SimpleMemberMap(string columnName, PropertyInfo property)
{
if (columnName == null)
throw new ArgumentNullException("columnName");
throw new ArgumentNullException(nameof(columnName));
if (property == null)
throw new ArgumentNullException("property");
throw new ArgumentNullException(nameof(property));
_columnName = columnName;
_property = property;
ColumnName = columnName;
Property = property;
}
/// <summary>
......@@ -38,13 +33,13 @@ public SimpleMemberMap(string columnName, PropertyInfo property)
public SimpleMemberMap(string columnName, FieldInfo field)
{
if (columnName == null)
throw new ArgumentNullException("columnName");
throw new ArgumentNullException(nameof(columnName));
if (field == null)
throw new ArgumentNullException("field");
throw new ArgumentNullException(nameof(field));
_columnName = columnName;
_field = field;
ColumnName = columnName;
Field = field;
}
/// <summary>
......@@ -55,66 +50,39 @@ public SimpleMemberMap(string columnName, FieldInfo field)
public SimpleMemberMap(string columnName, ParameterInfo parameter)
{
if (columnName == null)
throw new ArgumentNullException("columnName");
throw new ArgumentNullException(nameof(columnName));
if (parameter == null)
throw new ArgumentNullException("parameter");
throw new ArgumentNullException(nameof(parameter));
_columnName = columnName;
_parameter = parameter;
ColumnName = columnName;
Parameter = parameter;
}
/// <summary>
/// DataReader column name
/// </summary>
public string ColumnName
{
get { return _columnName; }
}
public string ColumnName { get; }
/// <summary>
/// Target member type
/// </summary>
public Type MemberType
{
get
{
if (_field != null)
return _field.FieldType;
if (_property != null)
return _property.PropertyType;
if (_parameter != null)
return _parameter.ParameterType;
return null;
}
}
public Type MemberType => Field?.FieldType ?? Property?.PropertyType ?? Parameter?.ParameterType;
/// <summary>
/// Target property
/// </summary>
public PropertyInfo Property
{
get { return _property; }
}
public PropertyInfo Property { get; }
/// <summary>
/// Target field
/// </summary>
public FieldInfo Field
{
get { return _field; }
}
public FieldInfo Field { get; }
/// <summary>
/// Target constructor parameter
/// </summary>
public ParameterInfo Parameter
{
get { return _parameter; }
}
public ParameterInfo Parameter { get; }
}
}
......@@ -5,7 +5,7 @@
#if !DNXCORE50
namespace Dapper
{
sealed class SqlDataRecordHandler : Dapper.SqlMapper.ITypeHandler
sealed class SqlDataRecordHandler : SqlMapper.ITypeHandler
{
public object Parse(Type destinationType, object value)
{
......
......@@ -9,7 +9,7 @@ namespace Dapper
/// <summary>
/// Used to pass a IEnumerable&lt;SqlDataRecord&gt; as a SqlDataRecordListTVPParameter
/// </summary>
sealed class SqlDataRecordListTVPParameter : Dapper.SqlMapper.ICustomQueryParameter
sealed class SqlDataRecordListTVPParameter : SqlMapper.ICustomQueryParameter
{
private readonly IEnumerable<Microsoft.SqlServer.Server.SqlDataRecord> data;
private readonly string typeName;
......
......@@ -60,7 +60,7 @@ public static Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn, string
/// </summary>
public static Task<IEnumerable<object>> QueryAsync(this IDbConnection cnn, Type type, string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null)
{
if (type == null) throw new ArgumentNullException("type");
if (type == null) throw new ArgumentNullException(nameof(type));
return QueryAsync<object>(cnn, type, new CommandDefinition(sql, (object)param, transaction, commandTimeout, commandType, CommandFlags.Buffered, default(CancellationToken)));
}
......@@ -83,7 +83,7 @@ public static Task<IEnumerable<object>> QueryAsync(this IDbConnection cnn, Type
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 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;
......@@ -94,7 +94,7 @@ private static async Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn,
{
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)
......@@ -121,7 +121,7 @@ private static async Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn,
buffer.Add((T)Convert.ChangeType(val, convertToType, CultureInfo.InvariantCulture));
}
}
while (await reader.NextResultAsync(cancel).ConfigureAwait(false)) { }
command.OnCompleted();
......@@ -135,13 +135,13 @@ private static async Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn,
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();
}
}
}
......@@ -170,15 +170,15 @@ public static Task<int> ExecuteAsync(this IDbConnection cnn, CommandDefinition c
return ExecuteImplAsync(cnn, command, param);
}
}
private struct AsyncExecState
{
public readonly DbCommand Command;
public readonly Task<int> Task;
public AsyncExecState(DbCommand command, Task<int> task)
{
this.Command = command;
this.Task = task;
Command = command;
Task = task;
}
}
private static async Task<int> ExecuteMultiImplAsync(IDbConnection cnn, CommandDefinition command, IEnumerable multiExec)
......@@ -189,7 +189,7 @@ private static async Task<int> ExecuteMultiImplAsync(IDbConnection cnn, CommandD
try
{
if (wasClosed) await ((DbConnection)cnn).OpenAsync(command.CancellationToken).ConfigureAwait(false);
CacheInfo info = null;
string masterSql = null;
if ((command.Flags & CommandFlags.Pipelined) != 0)
......@@ -276,7 +276,7 @@ private static async Task<int> ExecuteMultiImplAsync(IDbConnection cnn, CommandD
}
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 identity = new Identity(command.CommandText, command.CommandType, cnn, 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))
......@@ -503,15 +503,15 @@ private static async Task<int> ExecuteImplAsync(IDbConnection cnn, CommandDefini
/// <param name="commandTimeout">Number of seconds before command execution timeout</param>
/// <param name="commandType">Is it a stored proc or a batch?</param>
/// <returns></returns>
public static Task<IEnumerable<TReturn>> QueryAsync<TReturn>(this IDbConnection cnn, string sql, Type[] types, Func<object[], TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null)
public static Task<IEnumerable<TReturn>> QueryAsync<TReturn>(this IDbConnection cnn, string sql, Type[] types, Func<object[], TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null)
{
var command = new CommandDefinition(sql, (object)param, transaction, commandTimeout, commandType, buffered ? CommandFlags.Buffered : CommandFlags.None, default(CancellationToken));
return MultiMapAsync<TReturn>(cnn, command, types, map, splitOn);
}
private static async Task<IEnumerable<TReturn>> MultiMapAsync<TReturn>(this IDbConnection cnn, CommandDefinition command, Type[] types, Func<object[], TReturn> map, string splitOn)
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)
if (types.Length < 1)
{
throw new ArgumentException("you must provide at least one type to deserialize");
}
......@@ -542,8 +542,7 @@ private static IEnumerable<T> ExecuteReaderSync<T>(IDataReader reader, Func<IDat
yield return (T)func(reader);
}
while (reader.NextResult()) { }
if (parameters is SqlMapper.IParameterCallbacks)
((SqlMapper.IParameterCallbacks)parameters).OnCompleted();
(parameters as IParameterCallbacks)?.OnCompleted();
}
}
......@@ -598,7 +597,7 @@ public static async Task<GridReader> QueryMultipleAsync(this IDbConnection cnn,
{ /* don't spoil the existing exception */ }
reader.Dispose();
}
if (cmd != null) cmd.Dispose();
cmd?.Dispose();
if (wasClosed) cnn.Close();
throw;
}
......@@ -666,7 +665,7 @@ private static async Task<IDataReader> ExecuteReaderImplAsync(IDbConnection cnn,
finally
{
if (wasClosed) cnn.Close();
if (cmd != null) cmd.Dispose();
cmd?.Dispose();
}
}
......@@ -743,7 +742,7 @@ private async static Task<T> ExecuteScalarImplAsync<T>(IDbConnection cnn, Comman
finally
{
if (wasClosed) cnn.Close();
if (cmd != null) cmd.Dispose();
cmd?.Dispose();
}
return Parse<T>(result);
}
......
......@@ -17,8 +17,8 @@ private sealed class DapperRow
public DapperRow(DapperTable table, object[] values)
{
if (table == null) throw new ArgumentNullException("table");
if (values == null) throw new ArgumentNullException("values");
if (table == null) throw new ArgumentNullException(nameof(table));
if (values == null) throw new ArgumentNullException(nameof(values));
this.table = table;
this.values = values;
}
......@@ -136,11 +136,7 @@ IEnumerator IEnumerable.GetEnumerator()
return dic.Remove(item.Key);
}
bool ICollection<KeyValuePair<string, object>>.IsReadOnly
{
get { return false; }
}
bool ICollection<KeyValuePair<string, object>>.IsReadOnly => false;
#endregion
#region Implementation of IDictionary<string,object>
......@@ -177,7 +173,7 @@ public object SetValue(string key, object value)
}
private object SetValue(string key, object value, bool isAdd)
{
if (key == null) throw new ArgumentNullException("key");
if (key == null) throw new ArgumentNullException(nameof(key));
int index = table.IndexOfName(key);
if (index < 0)
{
......@@ -186,7 +182,7 @@ private object SetValue(string key, object value, bool isAdd)
else if (isAdd && index < values.Length && !(values[index] is DeadValue))
{
// then semantically, this value already exists
throw new ArgumentException("An item with the same key has already been added", "key");
throw new ArgumentException("An item with the same key has already been added", nameof(key));
}
int oldLength = values.Length;
if (oldLength <= index)
......
......@@ -10,11 +10,11 @@ private sealed class DapperTable
string[] fieldNames;
readonly Dictionary<string, int> fieldNameLookup;
internal string[] FieldNames { get { return fieldNames; } }
internal string[] FieldNames => fieldNames;
public DapperTable(string[] fieldNames)
{
if (fieldNames == null) throw new ArgumentNullException("fieldNames");
if (fieldNames == null) throw new ArgumentNullException(nameof(fieldNames));
this.fieldNames = fieldNames;
fieldNameLookup = new Dictionary<string, int>(fieldNames.Length, StringComparer.Ordinal);
......@@ -33,7 +33,7 @@ internal int IndexOfName(string name)
}
internal int AddField(string name)
{
if (name == null) throw new ArgumentNullException("name");
if (name == null) throw new ArgumentNullException(nameof(name));
if (fieldNameLookup.ContainsKey(name)) throw new InvalidOperationException("Field already exists: " + name);
int oldLen = fieldNames.Length;
Array.Resize(ref fieldNames, oldLen + 1); // yes, this is sub-optimal, but this is not the expected common case
......@@ -48,7 +48,7 @@ internal bool FieldExists(string key)
return key != null && fieldNameLookup.ContainsKey(key);
}
public int FieldCount { get { return fieldNames.Length; } }
public int FieldCount => fieldNames.Length;
}
}
......
......@@ -45,7 +45,7 @@ public Task<IEnumerable<dynamic>> ReadAsync(bool buffered = true)
/// </summary>
public Task<IEnumerable<object>> ReadAsync(Type type, bool buffered = true)
{
if (type == null) throw new ArgumentNullException("type");
if (type == null) throw new ArgumentNullException(nameof(type));
return ReadAsyncImpl<object>(type, buffered);
}
/// <summary>
......@@ -62,7 +62,7 @@ private async Task NextResultAsync()
{
readCount++;
gridIndex++;
consumed = false;
IsConsumed = false;
}
else
{
......@@ -70,7 +70,7 @@ private async Task NextResultAsync()
// need for "Cancel" etc
reader.Dispose();
reader = null;
if (callbacks != null) callbacks.OnCompleted();
callbacks?.OnCompleted();
Dispose();
}
}
......@@ -78,7 +78,7 @@ private async Task NextResultAsync()
private Task<IEnumerable<T>> ReadAsyncImpl<T>(Type type, bool buffered)
{
if (reader == null) throw new ObjectDisposedException(GetType().FullName, "The reader has been disposed; this can happen after all data has been consumed");
if (consumed) throw new InvalidOperationException("Query results must be consumed in the correct order, and each result can only be consumed once");
if (IsConsumed) throw new InvalidOperationException("Query results must be consumed in the correct order, and each result can only be consumed once");
var typedIdentity = identity.ForGrid(type, gridIndex);
CacheInfo cache = GetCacheInfo(typedIdentity, null, addToCache);
var deserializer = cache.Deserializer;
......@@ -89,8 +89,8 @@ private Task<IEnumerable<T>> ReadAsyncImpl<T>(Type type, bool buffered)
deserializer = new DeserializerState(hash, GetDeserializer(type, reader, 0, -1, false));
cache.Deserializer = deserializer;
}
consumed = true;
if (buffered && this.reader is DbDataReader)
IsConsumed = true;
if (buffered && reader is DbDataReader)
{
return ReadBufferedAsync<T>(gridIndex, deserializer.Func, typedIdentity);
}
......@@ -104,27 +104,23 @@ private Task<IEnumerable<T>> ReadAsyncImpl<T>(Type type, bool buffered)
private async Task<IEnumerable<T>> ReadBufferedAsync<T>(int index, Func<IDataReader, object> deserializer, Identity typedIdentity)
{
//try
//{
var reader = (DbDataReader)this.reader;
List<T> buffer = new List<T>();
while (index == gridIndex && await reader.ReadAsync(cancel).ConfigureAwait(false))
try
{
buffer.Add((T)deserializer(reader));
var reader = (DbDataReader)this.reader;
List<T> buffer = new List<T>();
while (index == gridIndex && await reader.ReadAsync(cancel).ConfigureAwait(false))
{
buffer.Add((T)deserializer(reader));
}
return buffer;
}
if (index == gridIndex) // need to do this outside of the finally pre-C#6
finally // finally so that First etc progresses things even when multiple rows
{
await NextResultAsync().ConfigureAwait(false);
if (index == gridIndex)
{
await NextResultAsync().ConfigureAwait(false);
}
}
return buffer;
//}
//finally // finally so that First etc progresses things even when multiple rows
//{
// if (index == gridIndex)
// {
// await NextResultAsync().ConfigureAwait(false);
// }
//}
}
}
......
......@@ -22,18 +22,17 @@ partial class SqlMapper
{
/// <summary>
/// The grid reader provides interfaces for reading multiple result sets from a Dapper query
/// The grid reader provides interfaces for reading multiple result sets from a Dapper query
/// </summary>
public partial class GridReader : IDisposable
{
private IDataReader reader;
private IDbCommand command;
private Identity identity;
private bool addToCache;
internal GridReader(IDbCommand command, IDataReader reader, Identity identity, SqlMapper.IParameterCallbacks callbacks, bool addToCache)
internal GridReader(IDbCommand command, IDataReader reader, Identity identity, IParameterCallbacks callbacks, bool addToCache)
{
this.Command = command;
Command = command;
this.reader = reader;
this.identity = identity;
this.callbacks = callbacks;
......@@ -62,14 +61,14 @@ public IEnumerable<T> Read<T>(bool buffered = true)
/// </summary>
public IEnumerable<object> Read(Type type, bool buffered = true)
{
if (type == null) throw new ArgumentNullException("type");
if (type == null) throw new ArgumentNullException(nameof(type));
return ReadImpl<object>(type, buffered);
}
private IEnumerable<T> ReadImpl<T>(Type type, bool buffered)
{
if (reader == null) throw new ObjectDisposedException(GetType().FullName, "The reader has been disposed; this can happen after all data has been consumed");
if (consumed) throw new InvalidOperationException("Query results must be consumed in the correct order, and each result can only be consumed once");
if (IsConsumed) throw new InvalidOperationException("Query results must be consumed in the correct order, and each result can only be consumed once");
var typedIdentity = identity.ForGrid(type, gridIndex);
CacheInfo cache = GetCacheInfo(typedIdentity, null, addToCache);
var deserializer = cache.Deserializer;
......@@ -80,7 +79,7 @@ private IEnumerable<T> ReadImpl<T>(Type type, bool buffered)
deserializer = new DeserializerState(hash, GetDeserializer(type, reader, 0, -1, false));
cache.Deserializer = deserializer;
}
consumed = true;
IsConsumed = true;
var result = ReadDeferred<T>(gridIndex, deserializer.Func, typedIdentity);
return buffered ? result.ToList() : result;
}
......@@ -99,7 +98,7 @@ private IEnumerable<T> ReadImpl<T>(Type type, bool buffered)
}, gridIndex);
try
{
foreach (var r in SqlMapper.MultiMapImpl<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(null, default(CommandDefinition), func, splitOn, reader, identity, false))
foreach (var r in MultiMapImpl<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(null, default(CommandDefinition), func, splitOn, reader, identity, false))
{
yield return r;
}
......@@ -115,7 +114,7 @@ private IEnumerable<TReturn> MultiReadInternal<TReturn>(Type[] types, Func<objec
var identity = this.identity.ForGrid(typeof(TReturn), types, gridIndex);
try
{
foreach (var r in SqlMapper.MultiMapImpl<TReturn>(null, default(CommandDefinition), types, map, splitOn, reader, identity, false))
foreach (var r in MultiMapImpl<TReturn>(null, default(CommandDefinition), types, map, splitOn, reader, identity, false))
{
yield return r;
}
......@@ -205,34 +204,17 @@ private IEnumerable<T> ReadDeferred<T>(int index, Func<IDataReader, object> dese
}
}
private int gridIndex, readCount;
private bool consumed;
private SqlMapper.IParameterCallbacks callbacks;
private IParameterCallbacks callbacks;
/// <summary>
/// Has the underlying reader been consumed?
/// </summary>
public bool IsConsumed
{
get
{
return consumed;
}
}
public bool IsConsumed { get; private set; }
/// <summary>
/// The command associated with the reader
/// </summary>
public IDbCommand Command
{
get
{
return command;
}
set
{
command = value;
}
}
public IDbCommand Command { get; set; }
private void NextResult()
{
......@@ -240,7 +222,7 @@ private void NextResult()
{
readCount++;
gridIndex++;
consumed = false;
IsConsumed = false;
}
else
{
......@@ -248,7 +230,7 @@ private void NextResult()
// need for "Cancel" etc
reader.Dispose();
reader = null;
if (callbacks != null) callbacks.OnCompleted();
callbacks?.OnCompleted();
Dispose();
}
}
......@@ -259,7 +241,7 @@ public void Dispose()
{
if (reader != null)
{
if (!reader.IsClosed && Command != null) Command.Cancel();
if (!reader.IsClosed) Command?.Cancel();
reader.Dispose();
reader = null;
}
......
......@@ -58,22 +58,22 @@ private Identity(string sql, CommandType? commandType, string connectionString,
hashCode = 17; // we *know* we are using this in a dictionary, so pre-compute this
hashCode = hashCode * 23 + commandType.GetHashCode();
hashCode = hashCode * 23 + gridIndex.GetHashCode();
hashCode = hashCode * 23 + (sql == null ? 0 : sql.GetHashCode());
hashCode = hashCode * 23 + (type == null ? 0 : type.GetHashCode());
hashCode = hashCode * 23 + (sql?.GetHashCode() ?? 0);
hashCode = hashCode * 23 + (type?.GetHashCode() ?? 0);
if (otherTypes != null)
{
foreach (var t in otherTypes)
{
hashCode = hashCode * 23 + (t == null ? 0 : t.GetHashCode());
hashCode = hashCode * 23 + (t?.GetHashCode() ?? 0);
}
}
hashCode = hashCode * 23 + (connectionString == null ? 0 : SqlMapper.connectionStringComparer.GetHashCode(connectionString));
hashCode = hashCode * 23 + (parametersType == null ? 0 : parametersType.GetHashCode());
hashCode = hashCode * 23 + (connectionString == null ? 0 : connectionStringComparer.GetHashCode(connectionString));
hashCode = hashCode * 23 + (parametersType?.GetHashCode() ?? 0);
}
}
/// <summary>
///
///
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
......@@ -86,28 +86,28 @@ public override bool Equals(object obj)
/// </summary>
public readonly string sql;
/// <summary>
/// The command type
/// The command type
/// </summary>
public readonly CommandType? commandType;
/// <summary>
///
///
/// </summary>
public readonly int hashCode, gridIndex;
/// <summary>
///
///
/// </summary>
public readonly Type type;
/// <summary>
///
///
/// </summary>
public readonly string connectionString;
/// <summary>
///
///
/// </summary>
public readonly Type parametersType;
/// <summary>
///
///
/// </summary>
/// <returns></returns>
public override int GetHashCode()
......@@ -127,7 +127,7 @@ public bool Equals(Identity other)
type == other.type &&
sql == other.sql &&
commandType == other.commandType &&
SqlMapper.connectionStringComparer.Equals(connectionString, other.connectionString) &&
connectionStringComparer.Equals(connectionString, other.connectionString) &&
parametersType == other.parametersType;
}
}
......
......@@ -49,9 +49,9 @@ private Link(TKey key, TValue value, Link<TKey, TValue> tail)
Value = value;
Tail = tail;
}
public TKey Key { get; private set; }
public TValue Value { get; private set; }
public Link<TKey, TValue> Tail { get; private set; }
public TKey Key { get; }
public TValue Value { get; }
public Link<TKey, TValue> Tail { get; }
}
}
}
......@@ -9,20 +9,20 @@ partial class SqlMapper
/// </summary>
internal struct LiteralToken
{
private readonly string token, member;
/// <summary>
/// The text in the original command that should be replaced
/// </summary>
public string Token { get { return token; } }
public string Token { get; }
/// <summary>
/// The name of the member referred to by the token
/// </summary>
public string Member { get { return member; } }
public string Member { get; }
internal LiteralToken(string token, string member)
{
this.token = token;
this.member = member;
Token = token;
Member = member;
}
internal static readonly IList<LiteralToken> None = new LiteralToken[0];
......
This diff is collapsed.
......@@ -8,7 +8,7 @@ namespace Dapper
/// <summary>
/// Used to pass a DataTable as a TableValuedParameter
/// </summary>
sealed class TableValuedParameter : Dapper.SqlMapper.ICustomQueryParameter
sealed class TableValuedParameter : SqlMapper.ICustomQueryParameter
{
private readonly DataTable table;
private readonly string typeName;
......@@ -47,14 +47,14 @@ internal static void Set(IDbDataParameter parameter, DataTable table, string typ
parameter.Value = SqlMapper.SanitizeParameterValue(table);
if (string.IsNullOrEmpty(typeName) && table != null)
{
typeName = SqlMapper.GetTypeName(table);
typeName = table.GetTypeName();
}
if (!string.IsNullOrEmpty(typeName))
{
var sqlParam = parameter as System.Data.SqlClient.SqlParameter;
if (sqlParam != null)
{
if (setTypeName != null) setTypeName(sqlParam, typeName);
setTypeName?.Invoke(sqlParam, typeName);
sqlParam.SqlDbType = SqlDbType.Structured;
}
}
......
......@@ -252,23 +252,17 @@ public WrappedReader(IDbCommand cmd, IDataReader reader)
void IDataReader.Close()
{
if (reader != null) reader.Close();
reader?.Close();
}
int IDataReader.Depth
{
get { return Reader.Depth; }
}
int IDataReader.Depth => Reader.Depth;
DataTable IDataReader.GetSchemaTable()
{
return Reader.GetSchemaTable();
}
bool IDataReader.IsClosed
{
get { return reader == null ? true : reader.IsClosed; }
}
bool IDataReader.IsClosed => reader?.IsClosed ?? true;
bool IDataReader.NextResult()
{
......@@ -280,24 +274,18 @@ bool IDataReader.Read()
return Reader.Read();
}
int IDataReader.RecordsAffected
{
get { return Reader.RecordsAffected; }
}
int IDataReader.RecordsAffected => Reader.RecordsAffected;
void IDisposable.Dispose()
{
if (reader != null) reader.Close();
if (reader != null) reader.Dispose();
reader?.Close();
reader?.Dispose();
reader = null;
if (cmd != null) cmd.Dispose();
cmd?.Dispose();
cmd = null;
}
int IDataRecord.FieldCount
{
get { return Reader.FieldCount; }
}
int IDataRecord.FieldCount => Reader.FieldCount;
bool IDataRecord.GetBoolean(int i)
{
......@@ -409,15 +397,9 @@ bool IDataRecord.IsDBNull(int i)
return Reader.IsDBNull(i);
}
object IDataRecord.this[string name]
{
get { return Reader[name]; }
}
object IDataRecord.this[string name] => Reader[name];
object IDataRecord.this[int i]
{
get { return Reader[i]; }
}
object IDataRecord.this[int i] => Reader[i];
}
#endif
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment