Commit f6132344 authored by Nick Craver's avatar Nick Craver

Lots of code cleanup, no functional changes

parent f26967c6
This diff is collapsed.
This diff is collapsed.
...@@ -33,8 +33,7 @@ public override void SetValue(IDbDataParameter parameter, DbGeography value) ...@@ -33,8 +33,7 @@ public override void SetValue(IDbDataParameter parameter, DbGeography value)
parsed = SqlGeography.STGeomFromWKB(new SqlBytes(value.AsBinary()), value.CoordinateSystemId); parsed = SqlGeography.STGeomFromWKB(new SqlBytes(value.AsBinary()), value.CoordinateSystemId);
} }
parameter.Value = parsed ?? DBNull.Value; parameter.Value = parsed ?? DBNull.Value;
var sqlParameter = parameter as SqlParameter; if (parameter is SqlParameter sqlParameter)
if (sqlParameter != null)
{ {
sqlParameter.UdtTypeName = "geography"; sqlParameter.UdtTypeName = "geography";
} }
...@@ -47,9 +46,8 @@ public override void SetValue(IDbDataParameter parameter, DbGeography value) ...@@ -47,9 +46,8 @@ public override void SetValue(IDbDataParameter parameter, DbGeography value)
public override DbGeography Parse(object value) public override DbGeography Parse(object value)
{ {
if (value == null || value is DBNull) return null; if (value == null || value is DBNull) return null;
if (value is SqlGeography) if (value is SqlGeography geo)
{ {
var geo = (SqlGeography)value;
return DbGeography.FromBinary(geo.STAsBinary().Value); return DbGeography.FromBinary(geo.STAsBinary().Value);
} }
return DbGeography.FromText(value.ToString()); return DbGeography.FromText(value.ToString());
......
...@@ -46,9 +46,8 @@ public override void SetValue(IDbDataParameter parameter, DbGeometry value) ...@@ -46,9 +46,8 @@ public override void SetValue(IDbDataParameter parameter, DbGeometry value)
public override DbGeometry Parse(object value) public override DbGeometry Parse(object value)
{ {
if (value == null || value is DBNull) return null; if (value == null || value is DBNull) return null;
if (value is SqlGeometry) if (value is SqlGeometry geo)
{ {
var geo = (SqlGeometry)value;
return DbGeometry.FromBinary(geo.STAsBinary().Value); return DbGeometry.FromBinary(geo.STAsBinary().Value);
} }
return DbGeometry.FromText(value.ToString()); return DbGeometry.FromText(value.ToString());
......
...@@ -131,21 +131,19 @@ public IEnumerable<T> All() ...@@ -131,21 +131,19 @@ public IEnumerable<T> All()
internal static List<string> GetParamNames(object o) internal static List<string> GetParamNames(object o)
{ {
var parameters = o as DynamicParameters; if (o is DynamicParameters parameters)
if (parameters != null)
{ {
return parameters.ParameterNames.ToList(); return parameters.ParameterNames.ToList();
} }
List<string> paramNames; if (!paramNameCache.TryGetValue(o.GetType(), out List<string> paramNames))
if (!paramNameCache.TryGetValue(o.GetType(), out paramNames))
{ {
paramNames = new List<string>(); paramNames = new List<string>();
foreach (var prop in o.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(p => p.GetGetMethod(false) != null)) foreach (var prop in o.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(p => p.GetGetMethod(false) != null))
{ {
var attribs = prop.GetCustomAttributes(typeof(IgnorePropertyAttribute), true); var attribs = prop.GetCustomAttributes(typeof(IgnorePropertyAttribute), true);
var attr = attribs.FirstOrDefault() as IgnorePropertyAttribute; var attr = attribs.FirstOrDefault() as IgnorePropertyAttribute;
if (attr==null || (!attr.Value)) if (attr == null || (!attr.Value))
{ {
paramNames.Add(prop.Name); paramNames.Add(prop.Name);
} }
...@@ -196,10 +194,7 @@ internal void InitDatabase(DbConnection connection, int commandTimeout) ...@@ -196,10 +194,7 @@ internal void InitDatabase(DbConnection connection, int commandTimeout)
{ {
_connection = connection; _connection = connection;
_commandTimeout = commandTimeout; _commandTimeout = commandTimeout;
if (tableConstructor == null) tableConstructor = tableConstructor ?? CreateTableConstructorForTable();
{
tableConstructor = CreateTableConstructorForTable();
}
tableConstructor(this as TDatabase); tableConstructor(this as TDatabase);
} }
...@@ -297,12 +292,10 @@ protected Action<TDatabase> CreateTableConstructor(params Type[] tableTypes) ...@@ -297,12 +292,10 @@ protected Action<TDatabase> CreateTableConstructor(params Type[] tableTypes)
return (Action<TDatabase>)dm.CreateDelegate(typeof(Action<TDatabase>)); return (Action<TDatabase>)dm.CreateDelegate(typeof(Action<TDatabase>));
} }
private static ConcurrentDictionary<Type, string> tableNameMap = new ConcurrentDictionary<Type, string>(); private static readonly ConcurrentDictionary<Type, string> tableNameMap = new ConcurrentDictionary<Type, string>();
private string DetermineTableName<T>(string likelyTableName) private string DetermineTableName<T>(string likelyTableName)
{ {
string name; if (!tableNameMap.TryGetValue(typeof(T), out string name))
if (!tableNameMap.TryGetValue(typeof(T), out name))
{ {
name = likelyTableName; name = likelyTableName;
if (!TableExists(name)) if (!TableExists(name))
...@@ -345,10 +338,8 @@ private bool TableExists(string name) ...@@ -345,10 +338,8 @@ private bool TableExists(string name)
/// <param name="sql">The SQL to execute.</param> /// <param name="sql">The SQL to execute.</param>
/// <param name="param">The parameters to use.</param> /// <param name="param">The parameters to use.</param>
/// <returns>The number of rows affected.</returns> /// <returns>The number of rows affected.</returns>
public int Execute(string sql, dynamic param = null) public int Execute(string sql, dynamic param = null) =>
{ _connection.Execute(sql, param as object, _transaction, _commandTimeout);
return _connection.Execute(sql, param as object, _transaction, _commandTimeout);
}
/// <summary> /// <summary>
/// Queries the current database. /// Queries the current database.
...@@ -358,10 +349,8 @@ public int Execute(string sql, dynamic param = null) ...@@ -358,10 +349,8 @@ public int Execute(string sql, dynamic param = null)
/// <param name="param">The parameters to use.</param> /// <param name="param">The parameters to use.</param>
/// <param name="buffered">Whether to buffer the results.</param> /// <param name="buffered">Whether to buffer the results.</param>
/// <returns>An enumerable of <typeparamref name="T"/> for the rows fetched.</returns> /// <returns>An enumerable of <typeparamref name="T"/> for the rows fetched.</returns>
public IEnumerable<T> Query<T>(string sql, dynamic param = null, bool buffered = true) public IEnumerable<T> Query<T>(string sql, dynamic param = null, bool buffered = true) =>
{ _connection.Query<T>(sql, param as object, _transaction, buffered, _commandTimeout);
return _connection.Query<T>(sql, param as object, _transaction, buffered, _commandTimeout);
}
/// <summary> /// <summary>
/// Queries the current database for a single record. /// Queries the current database for a single record.
...@@ -370,42 +359,32 @@ public IEnumerable<T> Query<T>(string sql, dynamic param = null, bool buffered = ...@@ -370,42 +359,32 @@ public IEnumerable<T> Query<T>(string sql, dynamic param = null, bool buffered =
/// <param name="sql">The SQL to execute.</param> /// <param name="sql">The SQL to execute.</param>
/// <param name="param">The parameters to use.</param> /// <param name="param">The parameters to use.</param>
/// <returns>An enumerable of <typeparamref name="T"/> for the rows fetched.</returns> /// <returns>An enumerable of <typeparamref name="T"/> for the rows fetched.</returns>
public T QueryFirstOrDefault<T>(string sql, dynamic param = null) public T QueryFirstOrDefault<T>(string sql, dynamic param = null) =>
{ _connection.QueryFirstOrDefault<T>(sql, param as object, _transaction, _commandTimeout);
return _connection.QueryFirstOrDefault<T>(sql, param as object, _transaction, _commandTimeout);
}
/// <summary> /// <summary>
/// Perform a multi mapping query with 2 input parameters /// Perform a multi mapping query with 2 input parameters
/// </summary> /// </summary>
public IEnumerable<TReturn> Query<TFirst, TSecond, TReturn>(string sql, Func<TFirst, TSecond, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null) public IEnumerable<TReturn> Query<TFirst, TSecond, TReturn>(string sql, Func<TFirst, TSecond, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null) =>
{ _connection.Query(sql, map, param as object, transaction, buffered, splitOn, commandTimeout);
return _connection.Query(sql, map, param as object, transaction, buffered, splitOn, commandTimeout);
}
/// <summary> /// <summary>
/// Perform a multi mapping query with 3 input parameters /// Perform a multi mapping query with 3 input parameters
/// </summary> /// </summary>
public IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TReturn>(string sql, Func<TFirst, TSecond, TThird, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null) public IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TReturn>(string sql, Func<TFirst, TSecond, TThird, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null) =>
{ _connection.Query(sql, map, param as object, transaction, buffered, splitOn, commandTimeout);
return _connection.Query(sql, map, param as object, transaction, buffered, splitOn, commandTimeout);
}
/// <summary> /// <summary>
/// Perform a multi mapping query with 4 input parameters /// Perform a multi mapping query with 4 input parameters
/// </summary> /// </summary>
public IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TReturn>(string sql, Func<TFirst, TSecond, TThird, TFourth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null) public IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TReturn>(string sql, Func<TFirst, TSecond, TThird, TFourth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null) =>
{ _connection.Query(sql, map, param as object, transaction, buffered, splitOn, commandTimeout);
return _connection.Query(sql, map, param as object, transaction, buffered, splitOn, commandTimeout);
}
/// <summary> /// <summary>
/// Perform a multi mapping query with 5 input parameters /// Perform a multi mapping query with 5 input parameters
/// </summary> /// </summary>
public IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(string sql, Func<TFirst, TSecond, TThird, TFourth, TFifth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null) public IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(string sql, Func<TFirst, TSecond, TThird, TFourth, TFifth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null) =>
{ _connection.Query(sql, map, param as object, transaction, buffered, splitOn, commandTimeout);
return _connection.Query(sql, map, param as object, transaction, buffered, splitOn, commandTimeout);
}
/// <summary> /// <summary>
/// Return a sequence of dynamic objects with properties matching the columns /// Return a sequence of dynamic objects with properties matching the columns
...@@ -414,18 +393,14 @@ public T QueryFirstOrDefault<T>(string sql, dynamic param = null) ...@@ -414,18 +393,14 @@ public T QueryFirstOrDefault<T>(string sql, dynamic param = null)
/// <param name="param">The parameters to use.</param> /// <param name="param">The parameters to use.</param>
/// <param name="buffered">Whether the results should be buffered in memory.</param> /// <param name="buffered">Whether the results should be buffered in memory.</param>
/// <remarks>Note: each row can be accessed via "dynamic", or by casting to an IDictionary&lt;string,object&gt;</remarks> /// <remarks>Note: each row can be accessed via "dynamic", or by casting to an IDictionary&lt;string,object&gt;</remarks>
public IEnumerable<dynamic> Query(string sql, dynamic param = null, bool buffered = true) public IEnumerable<dynamic> Query(string sql, dynamic param = null, bool buffered = true) =>
{ _connection.Query(sql, param as object, _transaction, buffered);
return _connection.Query(sql, param as object, _transaction, buffered);
}
/// <summary> /// <summary>
/// Execute a command that returns multiple result sets, and access each in turn /// Execute a command that returns multiple result sets, and access each in turn
/// </summary> /// </summary>
public SqlMapper.GridReader QueryMultiple(string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null) public SqlMapper.GridReader QueryMultiple(string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null) =>
{ SqlMapper.QueryMultiple(_connection, sql, param, transaction, commandTimeout, commandType);
return SqlMapper.QueryMultiple(_connection, sql, param, transaction, commandTimeout, commandType);
}
/// <summary> /// <summary>
/// Disposes the current database, rolling back current transactions. /// Disposes the current database, rolling back current transactions.
......
...@@ -84,15 +84,15 @@ private static DynamicParameters Diff(T original, T current) ...@@ -84,15 +84,15 @@ private static DynamicParameters Diff(T original, T current)
return dm; return dm;
} }
static List<PropertyInfo> RelevantProperties() private static List<PropertyInfo> RelevantProperties()
{ {
return typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) return typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Where(p => .Where(p =>
p.GetSetMethod(true) != null && p.GetSetMethod(true) != null
p.GetGetMethod(true) != null && && p.GetGetMethod(true) != null
(p.PropertyType == typeof(string) || && (p.PropertyType == typeof(string)
p.PropertyType.IsValueType() || || p.PropertyType.IsValueType()
(p.PropertyType.IsGenericType() && p.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))) || (p.PropertyType.IsGenericType() && p.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)))
).ToList(); ).ToList();
} }
...@@ -187,7 +187,6 @@ private static bool AreEqual<U>(U first, U second) ...@@ -187,7 +187,6 @@ private static bool AreEqual<U>(U first, U second)
return (Func<T, T, List<Change>>)dm.CreateDelegate(typeof(Func<T, T, List<Change>>)); return (Func<T, T, List<Change>>)dm.CreateDelegate(typeof(Func<T, T, List<Change>>));
} }
// adapted from https://stackoverflow.com/a/966466/17174 // adapted from https://stackoverflow.com/a/966466/17174
private static Func<T, T> GenerateCloner() private static Func<T, T> GenerateCloner()
{ {
......
...@@ -9,18 +9,16 @@ public class SqlBuilder ...@@ -9,18 +9,16 @@ public class SqlBuilder
private readonly Dictionary<string, Clauses> _data = new Dictionary<string, Clauses>(); private readonly Dictionary<string, Clauses> _data = new Dictionary<string, Clauses>();
private int _seq; private int _seq;
class Clause private class Clause
{ {
public string Sql { get; set; } public string Sql { get; set; }
public object Parameters { get; set; } public object Parameters { get; set; }
public bool IsInclusive { get; set; } public bool IsInclusive { get; set; }
} }
class Clauses : List<Clause> private class Clauses : List<Clause>
{ {
private readonly string _joiner; private readonly string _joiner, _prefix, _postfix;
private readonly string _prefix;
private readonly string _postfix;
public Clauses(string joiner, string prefix = "", string postfix = "") public Clauses(string joiner, string prefix = "", string postfix = "")
{ {
...@@ -66,11 +64,11 @@ public Template(SqlBuilder builder, string sql, dynamic parameters) ...@@ -66,11 +64,11 @@ public Template(SqlBuilder builder, string sql, dynamic parameters)
private static readonly Regex _regex = new Regex(@"\/\*\*.+?\*\*\/", RegexOptions.Compiled | RegexOptions.Multiline); private static readonly Regex _regex = new Regex(@"\/\*\*.+?\*\*\/", RegexOptions.Compiled | RegexOptions.Multiline);
void ResolveSql() private void ResolveSql()
{ {
if (_dataSeq != _builder._seq) if (_dataSeq != _builder._seq)
{ {
DynamicParameters p = new DynamicParameters(_initParams); var p = new DynamicParameters(_initParams);
rawSql = _sql; rawSql = _sql;
...@@ -87,100 +85,69 @@ void ResolveSql() ...@@ -87,100 +85,69 @@ void ResolveSql()
} }
} }
string rawSql; private string rawSql;
object parameters; private object parameters;
public string RawSql { get { ResolveSql(); return rawSql; } } public string RawSql
public object Parameters { get { ResolveSql(); return parameters; } } {
get { ResolveSql(); return rawSql; }
} }
public Template AddTemplate(string sql, dynamic parameters = null) public object Parameters
{ {
return new Template(this, sql, parameters); get { ResolveSql(); return parameters; }
}
} }
protected void AddClause(string name, string sql, object parameters, string joiner, string prefix = "", string postfix = "", bool isInclusive = false) public Template AddTemplate(string sql, dynamic parameters = null) =>
new Template(this, sql, parameters);
protected SqlBuilder AddClause(string name, string sql, object parameters, string joiner, string prefix = "", string postfix = "", bool isInclusive = false)
{ {
Clauses clauses; if (!_data.TryGetValue(name, out Clauses clauses))
if (!_data.TryGetValue(name, out clauses))
{ {
clauses = new Clauses(joiner, prefix, postfix); clauses = new Clauses(joiner, prefix, postfix);
_data[name] = clauses; _data[name] = clauses;
} }
clauses.Add(new Clause { Sql = sql, Parameters = parameters, IsInclusive = isInclusive }); clauses.Add(new Clause { Sql = sql, Parameters = parameters, IsInclusive = isInclusive });
_seq++; _seq++;
return this;
} }
public SqlBuilder Intersect(string sql, dynamic parameters = null) public SqlBuilder Intersect(string sql, dynamic parameters = null) =>
{
AddClause("intersect", sql, parameters, "\nINTERSECT\n ", "\n ", "\n", false); AddClause("intersect", sql, parameters, "\nINTERSECT\n ", "\n ", "\n", false);
return this;
}
public SqlBuilder InnerJoin(string sql, dynamic parameters = null) public SqlBuilder InnerJoin(string sql, dynamic parameters = null) =>
{
AddClause("innerjoin", sql, parameters, "\nINNER JOIN ", "\nINNER JOIN ", "\n", false); AddClause("innerjoin", sql, parameters, "\nINNER JOIN ", "\nINNER JOIN ", "\n", false);
return this;
}
public SqlBuilder LeftJoin(string sql, dynamic parameters = null) public SqlBuilder LeftJoin(string sql, dynamic parameters = null) =>
{
AddClause("leftjoin", sql, parameters, "\nLEFT JOIN ", "\nLEFT JOIN ", "\n", false); AddClause("leftjoin", sql, parameters, "\nLEFT JOIN ", "\nLEFT JOIN ", "\n", false);
return this;
}
public SqlBuilder RightJoin(string sql, dynamic parameters = null) public SqlBuilder RightJoin(string sql, dynamic parameters = null) =>
{
AddClause("rightjoin", sql, parameters, "\nRIGHT JOIN ", "\nRIGHT JOIN ", "\n", false); AddClause("rightjoin", sql, parameters, "\nRIGHT JOIN ", "\nRIGHT JOIN ", "\n", false);
return this;
}
public SqlBuilder Where(string sql, dynamic parameters = null) public SqlBuilder Where(string sql, dynamic parameters = null) =>
{
AddClause("where", sql, parameters, " AND ", "WHERE ", "\n", false); AddClause("where", sql, parameters, " AND ", "WHERE ", "\n", false);
return this;
}
public SqlBuilder OrWhere(string sql, dynamic parameters = null) public SqlBuilder OrWhere(string sql, dynamic parameters = null) =>
{
AddClause("where", sql, parameters, " OR ", "WHERE ", "\n", true); AddClause("where", sql, parameters, " OR ", "WHERE ", "\n", true);
return this;
}
public SqlBuilder OrderBy(string sql, dynamic parameters = null) public SqlBuilder OrderBy(string sql, dynamic parameters = null) =>
{
AddClause("orderby", sql, parameters, " , ", "ORDER BY ", "\n", false); AddClause("orderby", sql, parameters, " , ", "ORDER BY ", "\n", false);
return this;
}
public SqlBuilder Select(string sql, dynamic parameters = null) public SqlBuilder Select(string sql, dynamic parameters = null) =>
{
AddClause("select", sql, parameters, " , ", "", "\n", false); AddClause("select", sql, parameters, " , ", "", "\n", false);
return this;
}
public SqlBuilder AddParameters(dynamic parameters) public SqlBuilder AddParameters(dynamic parameters) =>
{
AddClause("--parameters", "", parameters, "", "", "", false); AddClause("--parameters", "", parameters, "", "", "", false);
return this;
}
public SqlBuilder Join(string sql, dynamic parameters = null) public SqlBuilder Join(string sql, dynamic parameters = null) =>
{
AddClause("join", sql, parameters, "\nJOIN ", "\nJOIN ", "\n", false); AddClause("join", sql, parameters, "\nJOIN ", "\nJOIN ", "\n", false);
return this;
}
public SqlBuilder GroupBy(string sql, dynamic parameters = null) public SqlBuilder GroupBy(string sql, dynamic parameters = null) =>
{
AddClause("groupby", sql, parameters, " , ", "\nGROUP BY ", "\n", false); AddClause("groupby", sql, parameters, " , ", "\nGROUP BY ", "\n", false);
return this;
}
public SqlBuilder Having(string sql, dynamic parameters = null) public SqlBuilder Having(string sql, dynamic parameters = null) =>
{
AddClause("having", sql, parameters, "\nAND ", "HAVING ", "\n", false); AddClause("having", sql, parameters, "\nAND ", "HAVING ", "\n", false);
return this;
}
} }
} }
...@@ -227,7 +227,7 @@ public void NullDateTime() ...@@ -227,7 +227,7 @@ public void NullDateTime()
connection.Insert(new Stuff { Name = "First item" }); connection.Insert(new Stuff { Name = "First item" });
connection.Insert(new Stuff { Name = "Second item", Created = DateTime.Now }); connection.Insert(new Stuff { Name = "Second item", Created = DateTime.Now });
var stuff = connection.Query<Stuff>("select * from Stuff").ToList(); var stuff = connection.Query<Stuff>("select * from Stuff").ToList();
stuff.First().Created.IsNull(); stuff[0].Created.IsNull();
stuff.Last().Created.IsNotNull(); stuff.Last().Created.IsNotNull();
} }
} }
......
...@@ -68,6 +68,7 @@ public static List<dynamic> ToExpandoList(this IDataReader rdr) ...@@ -68,6 +68,7 @@ public static List<dynamic> ToExpandoList(this IDataReader rdr)
} }
return result; return result;
} }
public static dynamic RecordToExpando(this IDataReader rdr) public static dynamic RecordToExpando(this IDataReader rdr)
{ {
dynamic e = new ExpandoObject(); dynamic e = new ExpandoObject();
...@@ -112,9 +113,9 @@ public static dynamic ToExpando(this object o) ...@@ -112,9 +113,9 @@ public static dynamic ToExpando(this object o)
/// </summary> /// </summary>
public class DynamicModel public class DynamicModel
{ {
DbProviderFactory _factory; private readonly DbProviderFactory _factory;
#pragma warning disable 0649 #pragma warning disable 0649
string _connectionString; private string _connectionString;
#pragma warning restore 0649 #pragma warning restore 0649
public DynamicModel(string connectionStringName = "", string tableName = "", string primaryKeyField = "") public DynamicModel(string connectionStringName = "", string tableName = "", string primaryKeyField = "")
...@@ -149,20 +150,20 @@ public virtual IEnumerable<dynamic> Query(string sql, params object[] args) ...@@ -149,20 +150,20 @@ public virtual IEnumerable<dynamic> Query(string sql, params object[] args)
var rdr = CreateCommand(sql, conn, args).ExecuteReader(); var rdr = CreateCommand(sql, conn, args).ExecuteReader();
while (rdr.Read()) while (rdr.Read())
{ {
yield return rdr.RecordToExpando(); ; yield return rdr.RecordToExpando();
} }
} }
} }
public virtual IEnumerable<dynamic> Query(string sql, DbConnection connection, params object[] args) public virtual IEnumerable<dynamic> Query(string sql, DbConnection connection, params object[] args)
{ {
using (var rdr = CreateCommand(sql, connection, args).ExecuteReader()) using (var rdr = CreateCommand(sql, connection, args).ExecuteReader())
{ {
while (rdr.Read()) while (rdr.Read())
{ {
yield return rdr.RecordToExpando(); ; yield return rdr.RecordToExpando();
} }
} }
} }
/// <summary> /// <summary>
/// Returns a single result /// Returns a single result
...@@ -179,7 +180,7 @@ public virtual object Scalar(string sql, params object[] args) ...@@ -179,7 +180,7 @@ public virtual object Scalar(string sql, params object[] args)
/// <summary> /// <summary>
/// Creates a DBCommand that you can use for loving your database. /// Creates a DBCommand that you can use for loving your database.
/// </summary> /// </summary>
DbCommand CreateCommand(string sql, DbConnection conn, params object[] args) private DbCommand CreateCommand(string sql, DbConnection conn, params object[] args)
{ {
var result = _factory.CreateCommand(); var result = _factory.CreateCommand();
result.Connection = conn; result.Connection = conn;
...@@ -230,6 +231,7 @@ public virtual int Save(params object[] things) ...@@ -230,6 +231,7 @@ public virtual int Save(params object[] things)
var commands = BuildCommands(things); var commands = BuildCommands(things);
return Execute(commands); return Execute(commands);
} }
public virtual int Execute(DbCommand command) public virtual int Execute(DbCommand command)
{ {
return Execute(new DbCommand[] { command }); return Execute(new DbCommand[] { command });
...@@ -255,6 +257,7 @@ public virtual int Execute(IEnumerable<DbCommand> commands) ...@@ -255,6 +257,7 @@ public virtual int Execute(IEnumerable<DbCommand> commands)
} }
return result; return result;
} }
public virtual string PrimaryKeyField { get; set; } public virtual string PrimaryKeyField { get; set; }
/// <summary> /// <summary>
/// Conventionally introspects the object passed in for a field that /// Conventionally introspects the object passed in for a field that
...@@ -270,10 +273,10 @@ public virtual bool HasPrimaryKey(object o) ...@@ -270,10 +273,10 @@ public virtual bool HasPrimaryKey(object o)
/// </summary> /// </summary>
public virtual object GetPrimaryKey(object o) public virtual object GetPrimaryKey(object o)
{ {
object result = null; o.ToDictionary().TryGetValue(PrimaryKeyField, out object result);
o.ToDictionary().TryGetValue(PrimaryKeyField, out result);
return result; return result;
} }
public virtual string TableName { get; set; } public virtual string TableName { get; set; }
/// <summary> /// <summary>
/// Creates a command for use with transactions - internal stuff mostly, but here for you to play with /// Creates a command for use with transactions - internal stuff mostly, but here for you to play with
...@@ -285,7 +288,7 @@ public virtual DbCommand CreateInsertCommand(object o) ...@@ -285,7 +288,7 @@ public virtual DbCommand CreateInsertCommand(object o)
var settings = (IDictionary<string, object>)expando; var settings = (IDictionary<string, object>)expando;
var sbKeys = new StringBuilder(); var sbKeys = new StringBuilder();
var sbVals = new StringBuilder(); var sbVals = new StringBuilder();
var stub = "INSERT INTO {0} ({1}) \r\n VALUES ({2})"; const string stub = "INSERT INTO {0} ({1}) \r\n VALUES ({2})";
result = CreateCommand(stub, null); result = CreateCommand(stub, null);
int counter = 0; int counter = 0;
foreach (var item in settings) foreach (var item in settings)
...@@ -299,10 +302,13 @@ public virtual DbCommand CreateInsertCommand(object o) ...@@ -299,10 +302,13 @@ public virtual DbCommand CreateInsertCommand(object o)
{ {
var keys = sbKeys.ToString().Substring(0, sbKeys.Length - 1); var keys = sbKeys.ToString().Substring(0, sbKeys.Length - 1);
var vals = sbVals.ToString().Substring(0, sbVals.Length - 1); var vals = sbVals.ToString().Substring(0, sbVals.Length - 1);
var sql = string.Format(stub, TableName, keys, vals); result.CommandText = string.Format(stub, TableName, keys, vals);
result.CommandText = sql;
} }
else throw new InvalidOperationException("Can't parse this object to the database - there are no properties set"); else
{
throw new InvalidOperationException("Can't parse this object to the database - there are no properties set");
}
return result; return result;
} }
/// <summary> /// <summary>
...@@ -313,7 +319,7 @@ public virtual DbCommand CreateUpdateCommand(object o, object key) ...@@ -313,7 +319,7 @@ public virtual DbCommand CreateUpdateCommand(object o, object key)
var expando = o.ToExpando(); var expando = o.ToExpando();
var settings = (IDictionary<string, object>)expando; var settings = (IDictionary<string, object>)expando;
var sbKeys = new StringBuilder(); var sbKeys = new StringBuilder();
var stub = "UPDATE {0} SET {1} WHERE {2} = @{3}"; const string stub = "UPDATE {0} SET {1} WHERE {2} = @{3}";
var args = new List<object>(); var args = new List<object>();
var result = CreateCommand(stub, null); var result = CreateCommand(stub, null);
int counter = 0; int counter = 0;
...@@ -335,7 +341,11 @@ public virtual DbCommand CreateUpdateCommand(object o, object key) ...@@ -335,7 +341,11 @@ public virtual DbCommand CreateUpdateCommand(object o, object key)
var keys = sbKeys.ToString().Substring(0, sbKeys.Length - 4); var keys = sbKeys.ToString().Substring(0, sbKeys.Length - 4);
result.CommandText = string.Format(stub, TableName, keys, PrimaryKeyField, counter); result.CommandText = string.Format(stub, TableName, keys, PrimaryKeyField, counter);
} }
else throw new InvalidOperationException("No parsable object was sent in - could not divine any name/value pairs"); else
{
throw new InvalidOperationException("No parsable object was sent in - could not divine any name/value pairs");
}
return result; return result;
} }
/// <summary> /// <summary>
...@@ -420,7 +430,7 @@ public virtual dynamic Paged(string where = "", string orderBy = "", string colu ...@@ -420,7 +430,7 @@ public virtual dynamic Paged(string where = "", string orderBy = "", string colu
} }
var sql = string.Format("SELECT {0} FROM (SELECT ROW_NUMBER() OVER (ORDER BY {2}) AS Row, {0} FROM {3} {4}) AS Paged ", columns, pageSize, orderBy, TableName, where); var sql = string.Format("SELECT {0} FROM (SELECT ROW_NUMBER() OVER (ORDER BY {2}) AS Row, {0} FROM {3} {4}) AS Paged ", columns, pageSize, orderBy, TableName, where);
var pageStart = (currentPage - 1) * pageSize; var pageStart = (currentPage - 1) * pageSize;
sql += string.Format(" WHERE Row >={0} AND Row <={1}", pageStart, (pageStart + pageSize)); sql += string.Format(" WHERE Row >={0} AND Row <={1}", pageStart, pageStart + pageSize);
countSQL += where; countSQL += where;
result.TotalRecords = Scalar(countSQL, args); result.TotalRecords = Scalar(countSQL, args);
result.TotalPages = result.TotalRecords / pageSize; result.TotalPages = result.TotalRecords / pageSize;
......
...@@ -50,6 +50,7 @@ public void Add(Action<int> iteration, string name) ...@@ -50,6 +50,7 @@ public void Add(Action<int> iteration, string name)
{ {
Add(new Test(iteration, name)); Add(new Test(iteration, name));
} }
public void AddAsync(Func<int, Task> iterationAsync, string name) public void AddAsync(Func<int, Task> iterationAsync, string name)
{ {
Add(new Test(iterationAsync, name)); Add(new Test(iterationAsync, name));
...@@ -156,7 +157,6 @@ public async Task RunAsync(int iterations) ...@@ -156,7 +157,6 @@ public async Task RunAsync(int iterations)
tests.Add(id => mapperConnection.Query<Post>("select * from Posts where Id = @Id", new { Id = id }, buffered: false).First(), "Dapper: Query (non-buffered)"); tests.Add(id => mapperConnection.Query<Post>("select * from Posts where Id = @Id", new { Id = id }, buffered: false).First(), "Dapper: Query (non-buffered)");
tests.Add(id => mapperConnection.QueryFirstOrDefault<Post>("select * from Posts where Id = @Id", new { Id = id }), "Dapper: QueryFirstOrDefault"); tests.Add(id => mapperConnection.QueryFirstOrDefault<Post>("select * from Posts where Id = @Id", new { Id = id }), "Dapper: QueryFirstOrDefault");
var mapperConnection2 = GetOpenConnection(); var mapperConnection2 = GetOpenConnection();
tests.Add(id => mapperConnection2.Query("select * from Posts where Id = @Id", new { Id = id }, buffered: true).First(), "Dapper: Dynamic Query (buffered)"); tests.Add(id => mapperConnection2.Query("select * from Posts where Id = @Id", new { Id = id }, buffered: true).First(), "Dapper: Dynamic Query (buffered)");
tests.Add(id => mapperConnection2.Query("select * from Posts where Id = @Id", new { Id = id }, buffered: false).First(), "Dapper: Dynamic Query (non-buffered)"); tests.Add(id => mapperConnection2.Query("select * from Posts where Id = @Id", new { Id = id }, buffered: false).First(), "Dapper: Dynamic Query (non-buffered)");
...@@ -291,10 +291,12 @@ public async Task RunAsync(int iterations) ...@@ -291,10 +291,12 @@ public async Task RunAsync(int iterations)
}, "ServiceStack.OrmLite"); }, "ServiceStack.OrmLite");
// Hand Coded // Hand Coded
var postCommand = new SqlCommand(); var postCommand = new SqlCommand()
postCommand.Connection = connection; {
postCommand.CommandText = @"select Id, [Text], [CreationDate], LastChangeDate, Connection = connection,
Counter1,Counter2,Counter3,Counter4,Counter5,Counter6,Counter7,Counter8,Counter9 from Posts where Id = @Id"; CommandText = @"select Id, [Text], [CreationDate], LastChangeDate,
Counter1,Counter2,Counter3,Counter4,Counter5,Counter6,Counter7,Counter8,Counter9 from Posts where Id = @Id"
};
var idParam = postCommand.Parameters.Add("@Id", SqlDbType.Int); var idParam = postCommand.Parameters.Add("@Id", SqlDbType.Int);
tests.Add(id => tests.Add(id =>
...@@ -337,7 +339,6 @@ public async Task RunAsync(int iterations) ...@@ -337,7 +339,6 @@ public async Task RunAsync(int iterations)
//var db1 = new DbManager(GetOpenConnection()); //var db1 = new DbManager(GetOpenConnection());
//tests.Add(id => db1.SetCommand("select * from Posts where Id = @id", db1.Parameter("id", id)).ExecuteList<Post>(), "BLToolkit"); //tests.Add(id => db1.SetCommand("select * from Posts where Id = @id", db1.Parameter("id", id)).ExecuteList<Post>(), "BLToolkit");
#if !COREFX #if !COREFX
var table = new DataTable var table = new DataTable
{ {
......
...@@ -12,7 +12,7 @@ namespace Dapper.Tests ...@@ -12,7 +12,7 @@ namespace Dapper.Tests
public class Tests : TestBase public class Tests : TestBase
{ {
private SqlConnection _marsConnection; private SqlConnection _marsConnection;
private SqlConnection marsConnection => _marsConnection ?? (_marsConnection = GetOpenConnection(true)); private SqlConnection MarsConnection => _marsConnection ?? (_marsConnection = GetOpenConnection(true));
[Fact] [Fact]
public async Task TestBasicStringUsageAsync() public async Task TestBasicStringUsageAsync()
...@@ -108,7 +108,7 @@ public async Task TestExecuteAsync() ...@@ -108,7 +108,7 @@ public async Task TestExecuteAsync()
} }
[Fact] [Fact]
public void TestExecuteClosedConnAsync() public void TestExecuteClosedConnAsyncInner()
{ {
var query = connection.ExecuteAsync("declare @foo table(id int not null); insert @foo values(@id);", new { id = 1 }); var query = connection.ExecuteAsync("declare @foo table(id int not null); insert @foo values(@id);", new { id = 1 });
var val = query.Result; var val = query.Result;
...@@ -323,15 +323,15 @@ public async Task LiteralInAsync() ...@@ -323,15 +323,15 @@ public async Task LiteralInAsync()
public async Task RunSequentialVersusParallelAsync() public async Task RunSequentialVersusParallelAsync()
{ {
var ids = Enumerable.Range(1, 20000).Select(id => new { id }).ToArray(); var ids = Enumerable.Range(1, 20000).Select(id => new { id }).ToArray();
await marsConnection.ExecuteAsync(new CommandDefinition("select @id", ids.Take(5), flags: CommandFlags.None)).ConfigureAwait(false); await MarsConnection.ExecuteAsync(new CommandDefinition("select @id", ids.Take(5), flags: CommandFlags.None)).ConfigureAwait(false);
var watch = Stopwatch.StartNew(); var watch = Stopwatch.StartNew();
await marsConnection.ExecuteAsync(new CommandDefinition("select @id", ids, flags: CommandFlags.None)).ConfigureAwait(false); await MarsConnection.ExecuteAsync(new CommandDefinition("select @id", ids, flags: CommandFlags.None)).ConfigureAwait(false);
watch.Stop(); watch.Stop();
Console.WriteLine("No pipeline: {0}ms", watch.ElapsedMilliseconds); Console.WriteLine("No pipeline: {0}ms", watch.ElapsedMilliseconds);
watch = Stopwatch.StartNew(); watch = Stopwatch.StartNew();
await marsConnection.ExecuteAsync(new CommandDefinition("select @id", ids, flags: CommandFlags.Pipelined)).ConfigureAwait(false); await MarsConnection.ExecuteAsync(new CommandDefinition("select @id", ids, flags: CommandFlags.Pipelined)).ConfigureAwait(false);
watch.Stop(); watch.Stop();
Console.WriteLine("Pipeline: {0}ms", watch.ElapsedMilliseconds); Console.WriteLine("Pipeline: {0}ms", watch.ElapsedMilliseconds);
} }
...@@ -340,15 +340,15 @@ public async Task RunSequentialVersusParallelAsync() ...@@ -340,15 +340,15 @@ public async Task RunSequentialVersusParallelAsync()
public void RunSequentialVersusParallelSync() public void RunSequentialVersusParallelSync()
{ {
var ids = Enumerable.Range(1, 20000).Select(id => new { id }).ToArray(); var ids = Enumerable.Range(1, 20000).Select(id => new { id }).ToArray();
marsConnection.Execute(new CommandDefinition("select @id", ids.Take(5), flags: CommandFlags.None)); MarsConnection.Execute(new CommandDefinition("select @id", ids.Take(5), flags: CommandFlags.None));
var watch = Stopwatch.StartNew(); var watch = Stopwatch.StartNew();
marsConnection.Execute(new CommandDefinition("select @id", ids, flags: CommandFlags.None)); MarsConnection.Execute(new CommandDefinition("select @id", ids, flags: CommandFlags.None));
watch.Stop(); watch.Stop();
Console.WriteLine("No pipeline: {0}ms", watch.ElapsedMilliseconds); Console.WriteLine("No pipeline: {0}ms", watch.ElapsedMilliseconds);
watch = Stopwatch.StartNew(); watch = Stopwatch.StartNew();
marsConnection.Execute(new CommandDefinition("select @id", ids, flags: CommandFlags.Pipelined)); MarsConnection.Execute(new CommandDefinition("select @id", ids, flags: CommandFlags.Pipelined));
watch.Stop(); watch.Stop();
Console.WriteLine("Pipeline: {0}ms", watch.ElapsedMilliseconds); Console.WriteLine("Pipeline: {0}ms", watch.ElapsedMilliseconds);
} }
...@@ -365,7 +365,7 @@ public void AssertNoCacheWorksForQueryMultiple() ...@@ -365,7 +365,7 @@ public void AssertNoCacheWorksForQueryMultiple()
int c, d; int c, d;
SqlMapper.PurgeQueryCache(); SqlMapper.PurgeQueryCache();
int before = SqlMapper.GetCachedSQLCount(); int before = SqlMapper.GetCachedSQLCount();
using (var multi = marsConnection.QueryMultiple(cmdDef)) using (var multi = MarsConnection.QueryMultiple(cmdDef))
{ {
c = multi.Read<int>().Single(); c = multi.Read<int>().Single();
d = multi.Read<int>().Single(); d = multi.Read<int>().Single();
...@@ -387,7 +387,7 @@ public async Task TypeBasedViaTypeAsync() ...@@ -387,7 +387,7 @@ public async Task TypeBasedViaTypeAsync()
{ {
Type type = Common.GetSomeType(); Type type = Common.GetSomeType();
dynamic actual = (await marsConnection.QueryAsync(type, "select @A as [A], @B as [B]", new { A = 123, B = "abc" }).ConfigureAwait(false)).FirstOrDefault(); dynamic actual = (await MarsConnection.QueryAsync(type, "select @A as [A], @B as [B]", new { A = 123, B = "abc" }).ConfigureAwait(false)).FirstOrDefault();
((object)actual).GetType().IsEqualTo(type); ((object)actual).GetType().IsEqualTo(type);
int a = actual.A; int a = actual.A;
string b = actual.B; string b = actual.B;
...@@ -400,7 +400,7 @@ public async Task TypeBasedViaTypeAsyncFirstOrDefault() ...@@ -400,7 +400,7 @@ public async Task TypeBasedViaTypeAsyncFirstOrDefault()
{ {
Type type = Common.GetSomeType(); Type type = Common.GetSomeType();
dynamic actual = await marsConnection.QueryFirstOrDefaultAsync(type, "select @A as [A], @B as [B]", new { A = 123, B = "abc" }).ConfigureAwait(false); dynamic actual = await MarsConnection.QueryFirstOrDefaultAsync(type, "select @A as [A], @B as [B]", new { A = 123, B = "abc" }).ConfigureAwait(false);
((object)actual).GetType().IsEqualTo(type); ((object)actual).GetType().IsEqualTo(type);
int a = actual.A; int a = actual.A;
string b = actual.B; string b = actual.B;
...@@ -715,7 +715,7 @@ public async Task TestMultiMapArbitraryMapsAsync() ...@@ -715,7 +715,7 @@ public async Task TestMultiMapArbitraryMapsAsync()
var data = (await connection.QueryAsync<ReviewBoard>(sql, types, mapper).ConfigureAwait(false)).ToList(); var data = (await connection.QueryAsync<ReviewBoard>(sql, types, mapper).ConfigureAwait(false)).ToList();
var p = data.First(); var p = data[0];
p.Id.IsEqualTo(1); p.Id.IsEqualTo(1);
p.Name.IsEqualTo("Review Board 1"); p.Name.IsEqualTo("Review Board 1");
p.User1.Id.IsEqualTo(1); p.User1.Id.IsEqualTo(1);
......
...@@ -88,7 +88,7 @@ private class _ExplicitConstructors ...@@ -88,7 +88,7 @@ private class _ExplicitConstructors
public int Field { get; set; } public int Field { get; set; }
public int Field_1 { get; set; } public int Field_1 { get; set; }
private bool WentThroughProperConstructor; private readonly bool WentThroughProperConstructor;
public _ExplicitConstructors() { } public _ExplicitConstructors() { }
......
...@@ -15,7 +15,7 @@ public FactUnlessCoreCLRAttribute(string url) ...@@ -15,7 +15,7 @@ public FactUnlessCoreCLRAttribute(string url)
this.Url = url; this.Url = url;
} }
public string Url { get; private set; } public string Url { get; }
} }
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
......
...@@ -85,8 +85,7 @@ public void Dispose() ...@@ -85,8 +85,7 @@ public void Dispose()
public bool QueueMessage(IMessageSinkMessage message) public bool QueueMessage(IMessageSinkMessage message)
{ {
var testFailed = message as ITestFailed; if (message is ITestFailed testFailed)
if (testFailed != null)
{ {
var exceptionType = testFailed.ExceptionTypes.FirstOrDefault(); var exceptionType = testFailed.ExceptionTypes.FirstOrDefault();
if (exceptionType == typeof(SkipTestException).FullName) if (exceptionType == typeof(SkipTestException).FullName)
......
...@@ -15,8 +15,7 @@ public void ParentChildIdentityAssociations() ...@@ -15,8 +15,7 @@ public void ParentChildIdentityAssociations()
var parents = connection.Query<Parent, Child, Parent>(@"select 1 as [Id], 1 as [Id] union all select 1,2 union all select 2,3 union all select 1,4 union all select 3,5", var parents = connection.Query<Parent, Child, Parent>(@"select 1 as [Id], 1 as [Id] union all select 1,2 union all select 2,3 union all select 1,4 union all select 3,5",
(parent, child) => (parent, child) =>
{ {
Parent found; if (!lookup.TryGetValue(parent.Id, out Parent found))
if (!lookup.TryGetValue(parent.Id, out found))
{ {
lookup.Add(parent.Id, found = parent); lookup.Add(parent.Id, found = parent);
} }
...@@ -63,7 +62,7 @@ public void TestMultiMap() ...@@ -63,7 +62,7 @@ public void TestMultiMap()
Order by p.Id"; Order by p.Id";
var data = connection.Query<Post, User, Post>(sql, (post, user) => { post.Owner = user; return post; }).ToList(); var data = connection.Query<Post, User, Post>(sql, (post, user) => { post.Owner = user; return post; }).ToList();
var p = data.First(); var p = data[0];
p.Content.IsEqualTo("Sams Post1"); p.Content.IsEqualTo("Sams Post1");
p.Id.IsEqualTo(1); p.Id.IsEqualTo(1);
...@@ -210,7 +209,7 @@ public void TestMultiMapDynamic() ...@@ -210,7 +209,7 @@ public void TestMultiMapDynamic()
Order by p.Id"; Order by p.Id";
var data = connection.Query<dynamic, dynamic, dynamic>(sql, (post, user) => { post.Owner = user; return post; }).ToList(); var data = connection.Query<dynamic, dynamic, dynamic>(sql, (post, user) => { post.Owner = user; return post; }).ToList();
var p = data.First(); var p = data[0];
// hairy extension method support for dynamics // hairy extension method support for dynamics
((string)p.Content).IsEqualTo("Sams Post1"); ((string)p.Content).IsEqualTo("Sams Post1");
...@@ -436,7 +435,7 @@ public void TestMultiMapArbitraryMaps() ...@@ -436,7 +435,7 @@ public void TestMultiMapArbitraryMaps()
var data = connection.Query<ReviewBoard>(sql, types, mapper).ToList(); var data = connection.Query<ReviewBoard>(sql, types, mapper).ToList();
var p = data.First(); var p = data[0];
p.Id.IsEqualTo(1); p.Id.IsEqualTo(1);
p.Name.IsEqualTo("Review Board 1"); p.Name.IsEqualTo("Review Board 1");
p.User1.Id.IsEqualTo(1); p.User1.Id.IsEqualTo(1);
...@@ -495,7 +494,7 @@ public void TestMultiMapGridReader() ...@@ -495,7 +494,7 @@ public void TestMultiMapGridReader()
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
{ {
var data = grid.Read<Post, User, Post>((post, user) => { post.Owner = user; return post; }).ToList(); var data = grid.Read<Post, User, Post>((post, user) => { post.Owner = user; return post; }).ToList();
var p = data.First(); var p = data[0];
p.Content.IsEqualTo("Sams Post1"); p.Content.IsEqualTo("Sams Post1");
p.Id.IsEqualTo(1); p.Id.IsEqualTo(1);
......
...@@ -482,7 +482,7 @@ public void SO29596645_TvpProperty() ...@@ -482,7 +482,7 @@ public void SO29596645_TvpProperty()
private class SO29596645_RuleTableValuedParameters : SqlMapper.IDynamicParameters private class SO29596645_RuleTableValuedParameters : SqlMapper.IDynamicParameters
{ {
private string parameterName; private readonly string parameterName;
public SO29596645_RuleTableValuedParameters(string parameterName) public SO29596645_RuleTableValuedParameters(string parameterName)
{ {
...@@ -506,7 +506,7 @@ public void AddParameters(IDbCommand command, SqlMapper.Identity identity) ...@@ -506,7 +506,7 @@ public void AddParameters(IDbCommand command, SqlMapper.Identity identity)
private class SO29596645_OrganisationDTO private class SO29596645_OrganisationDTO
{ {
public SO29596645_RuleTableValuedParameters Rules { get; private set; } public SO29596645_RuleTableValuedParameters Rules { get; }
public SO29596645_OrganisationDTO() public SO29596645_OrganisationDTO()
{ {
...@@ -1074,11 +1074,13 @@ public class MultipleParametersWithIndexerDeclaringType ...@@ -1074,11 +1074,13 @@ public class MultipleParametersWithIndexerDeclaringType
get { return null; } get { return null; }
set { } set { }
} }
public object this[object field, int index] public object this[object field, int index]
{ {
get { return null; } get { return null; }
set { } set { }
} }
public int B { get; set; } public int B { get; set; }
} }
......
...@@ -13,9 +13,11 @@ public class MySQLTests : TestBase ...@@ -13,9 +13,11 @@ public class MySQLTests : TestBase
string cs = IsAppVeyor string cs = IsAppVeyor
? "Server=localhost;Database=test;Uid=root;Pwd=Password12!;" ? "Server=localhost;Database=test;Uid=root;Pwd=Password12!;"
: "Server=localhost;Database=tests;Uid=test;Pwd=pass;"; : "Server=localhost;Database=tests;Uid=test;Pwd=pass;";
var csb = new MySql.Data.MySqlClient.MySqlConnectionStringBuilder(cs); var csb = new MySql.Data.MySqlClient.MySqlConnectionStringBuilder(cs)
csb.AllowZeroDateTime = allowZeroDatetime; {
csb.ConvertZeroDateTime = convertZeroDatetime; AllowZeroDateTime = allowZeroDatetime,
ConvertZeroDateTime = convertZeroDatetime
};
var conn = new MySql.Data.MySqlClient.MySqlConnection(csb.ConnectionString); var conn = new MySql.Data.MySqlClient.MySqlConnection(csb.ConnectionString);
if (open) conn.Open(); if (open) conn.Open();
return conn; return conn;
......
...@@ -30,7 +30,7 @@ public void MultiRSSqlCE() ...@@ -30,7 +30,7 @@ public void MultiRSSqlCE()
cnn.Execute("insert Authors values(1,'sam')"); cnn.Execute("insert Authors values(1,'sam')");
var data = cnn.Query<PostCE, AuthorCE, PostCE>(@"select * from Posts p left join Authors a on a.ID = p.AuthorID", (post, author) => { post.Author = author; return post; }).ToList(); var data = cnn.Query<PostCE, AuthorCE, PostCE>(@"select * from Posts p left join Authors a on a.ID = p.AuthorID", (post, author) => { post.Author = author; return post; }).ToList();
var firstPost = data.First(); var firstPost = data[0];
firstPost.Title.IsEqualTo("title"); firstPost.Title.IsEqualTo("title");
firstPost.Author.Name.IsEqualTo("sam"); firstPost.Author.Name.IsEqualTo("sam");
data[1].Author.IsNull(); data[1].Author.IsNull();
......
...@@ -105,8 +105,8 @@ public void TestReadDynamicWithGridReader() ...@@ -105,8 +105,8 @@ public void TestReadDynamicWithGridReader()
users.Count.IsEqualTo(2); users.Count.IsEqualTo(2);
posts.Count.IsEqualTo(3); posts.Count.IsEqualTo(3);
((int)users.First().Id).IsEqualTo(2); ((int)users[0].Id).IsEqualTo(2);
((int)posts.First().Id).IsEqualTo(3); ((int)posts[0].Id).IsEqualTo(3);
} }
finally finally
{ {
......
...@@ -34,7 +34,6 @@ public void TupleReturnValue_Works_ByPosition() ...@@ -34,7 +34,6 @@ public void TupleReturnValue_Works_ByPosition()
val.name.IsEqualTo("Fred"); val.name.IsEqualTo("Fred");
} }
[Fact] [Fact]
public void TupleReturnValue_TooManyColumns_Ignored() public void TupleReturnValue_TooManyColumns_Ignored()
{ {
...@@ -43,7 +42,6 @@ public void TupleReturnValue_TooManyColumns_Ignored() ...@@ -43,7 +42,6 @@ public void TupleReturnValue_TooManyColumns_Ignored()
val.name.IsEqualTo("Fred"); val.name.IsEqualTo("Fred");
} }
[Fact] [Fact]
public void TupleReturnValue_TooFewColumns_Unmapped() public void TupleReturnValue_TooFewColumns_Unmapped()
{ {
...@@ -61,6 +59,5 @@ public void TupleReturnValue_Works_NamesIgnored() ...@@ -61,6 +59,5 @@ public void TupleReturnValue_Works_NamesIgnored()
val.id.IsEqualTo(42); val.id.IsEqualTo(42);
val.name.IsEqualTo("Fred"); val.name.IsEqualTo("Fred");
} }
} }
} }
...@@ -135,8 +135,7 @@ private static Action<IDbCommand> GetInit(Type commandType) ...@@ -135,8 +135,7 @@ private static Action<IDbCommand> GetInit(Type commandType)
{ {
if (commandType == null) if (commandType == null)
return null; // GIGO return null; // GIGO
Action<IDbCommand> action; if (SqlMapper.Link<Type, Action<IDbCommand>>.TryGet(commandInitCache, commandType, out Action<IDbCommand> action))
if (SqlMapper.Link<Type, Action<IDbCommand>>.TryGet(commandInitCache, commandType, out action))
{ {
return action; return action;
} }
...@@ -176,12 +175,11 @@ private static Action<IDbCommand> GetInit(Type commandType) ...@@ -176,12 +175,11 @@ private static Action<IDbCommand> GetInit(Type commandType)
private 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); var prop = declaringType.GetProperty(name, BindingFlags.Public | BindingFlags.Instance);
if (prop != null && prop.CanWrite && prop.PropertyType == expectedType && prop.GetIndexParameters().Length == 0) if (prop?.CanWrite == true && prop.PropertyType == expectedType && prop.GetIndexParameters().Length == 0)
{ {
return prop.GetSetMethod(); return prop.GetSetMethod();
} }
return null; return null;
} }
} }
} }
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
namespace Dapper namespace Dapper
{ {
/// <summary> /// <summary>
/// Additional state flags that control command behaviour /// Additional state flags that control command behaviour
/// </summary> /// </summary>
...@@ -26,5 +25,4 @@ public enum CommandFlags ...@@ -26,5 +25,4 @@ public enum CommandFlags
/// </summary> /// </summary>
NoCache = 4, NoCache = 4,
} }
} }
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
namespace Dapper namespace Dapper
{ {
/// <summary> /// <summary>
/// Implements custom property mapping by user provided criteria (usually presence of some custom attribute with column to member mapping) /// Implements custom property mapping by user provided criteria (usually presence of some custom attribute with column to member mapping)
/// </summary> /// </summary>
...@@ -19,14 +18,8 @@ public sealed class CustomPropertyTypeMap : SqlMapper.ITypeMap ...@@ -19,14 +18,8 @@ public sealed class CustomPropertyTypeMap : SqlMapper.ITypeMap
/// <param name="propertySelector">Property selector based on target type and DataReader column name</param> /// <param name="propertySelector">Property selector based on target type and DataReader column name</param>
public CustomPropertyTypeMap(Type type, Func<Type, string, PropertyInfo> propertySelector) public CustomPropertyTypeMap(Type type, Func<Type, string, PropertyInfo> propertySelector)
{ {
if (type == null) _type = type ?? throw new ArgumentNullException(nameof(type));
throw new ArgumentNullException(nameof(type)); _propertySelector = propertySelector ?? throw new ArgumentNullException(nameof(propertySelector));
if (propertySelector == null)
throw new ArgumentNullException(nameof(propertySelector));
_type = type;
_propertySelector = propertySelector;
} }
/// <summary> /// <summary>
...@@ -35,19 +28,14 @@ public CustomPropertyTypeMap(Type type, Func<Type, string, PropertyInfo> propert ...@@ -35,19 +28,14 @@ public CustomPropertyTypeMap(Type type, Func<Type, string, PropertyInfo> propert
/// <param name="names">DataReader column names</param> /// <param name="names">DataReader column names</param>
/// <param name="types">DataReader column types</param> /// <param name="types">DataReader column types</param>
/// <returns>Default constructor</returns> /// <returns>Default constructor</returns>
public ConstructorInfo FindConstructor(string[] names, Type[] types) public ConstructorInfo FindConstructor(string[] names, Type[] types) =>
{ _type.GetConstructor(new Type[0]);
return _type.GetConstructor(new Type[0]);
}
/// <summary> /// <summary>
/// Always returns null /// Always returns null
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public ConstructorInfo FindExplicitConstructor() public ConstructorInfo FindExplicitConstructor() => null;
{
return null;
}
/// <summary> /// <summary>
/// Not implemented as far as default constructor used for all cases /// Not implemented as far as default constructor used for all cases
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
#if !COREFX #if !COREFX
namespace Dapper namespace Dapper
{ {
sealed class DataTableHandler : SqlMapper.ITypeHandler internal sealed class DataTableHandler : SqlMapper.ITypeHandler
{ {
public object Parse(Type destinationType, object value) public object Parse(Type destinationType, object value)
{ {
......
...@@ -27,7 +27,7 @@ public DefaultTypeMap(Type type) ...@@ -27,7 +27,7 @@ public DefaultTypeMap(Type type)
_type = type; _type = type;
} }
#if COREFX #if COREFX
static bool IsParameterMatch(ParameterInfo[] x, ParameterInfo[] y) private static bool IsParameterMatch(ParameterInfo[] x, ParameterInfo[] y)
{ {
if (ReferenceEquals(x, y)) return true; if (ReferenceEquals(x, y)) return true;
if (x == null || y == null) return false; if (x == null || y == null) return false;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
namespace Dapper namespace Dapper
{ {
partial class DynamicParameters public partial class DynamicParameters
{ {
// The type here is used to differentiate the cache by type via generics // The type here is used to differentiate the cache by type via generics
// ReSharper disable once UnusedTypeParameter // ReSharper disable once UnusedTypeParameter
......
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
namespace Dapper namespace Dapper
{ {
partial class DynamicParameters public partial class DynamicParameters
{ {
sealed class ParamInfo private sealed class ParamInfo
{ {
public string Name { get; set; } public string Name { get; set; }
public object Value { get; set; } public object Value { get; set; }
......
...@@ -12,27 +12,18 @@ ...@@ -12,27 +12,18 @@
namespace Dapper namespace Dapper
{ {
/// <summary> /// <summary>
/// A bag of parameters that can be passed to the Dapper Query and Execute methods /// A bag of parameters that can be passed to the Dapper Query and Execute methods
/// </summary> /// </summary>
public partial class DynamicParameters : SqlMapper.IDynamicParameters, SqlMapper.IParameterLookup, SqlMapper.IParameterCallbacks public partial class DynamicParameters : SqlMapper.IDynamicParameters, SqlMapper.IParameterLookup, SqlMapper.IParameterCallbacks
{ {
internal const DbType EnumerableMultiParameter = (DbType)(-1); internal const DbType EnumerableMultiParameter = (DbType)(-1);
static Dictionary<SqlMapper.Identity, Action<IDbCommand, object>> paramReaderCache = new Dictionary<SqlMapper.Identity, Action<IDbCommand, object>>(); private static readonly Dictionary<SqlMapper.Identity, Action<IDbCommand, object>> paramReaderCache = new Dictionary<SqlMapper.Identity, Action<IDbCommand, object>>();
private readonly Dictionary<string, ParamInfo> parameters = new Dictionary<string, ParamInfo>();
Dictionary<string, ParamInfo> parameters = new Dictionary<string, ParamInfo>(); private List<object> templates;
List<object> templates;
object SqlMapper.IParameterLookup.this[string name]
{
get
{
ParamInfo param;
return parameters.TryGetValue(name, out param) ? param.Value : null;
}
}
object SqlMapper.IParameterLookup.this[string name] =>
parameters.TryGetValue(name, out ParamInfo param) ? param.Value : null;
/// <summary> /// <summary>
/// construct a dynamic parameter bag /// construct a dynamic parameter bag
...@@ -135,7 +126,7 @@ public void Add(string name, object value, DbType? dbType, ParameterDirection? d ...@@ -135,7 +126,7 @@ public void Add(string name, object value, DbType? dbType, ParameterDirection? d
}; };
} }
static string Clean(string name) private static string Clean(string name)
{ {
if (!string.IsNullOrEmpty(name)) if (!string.IsNullOrEmpty(name))
{ {
...@@ -249,7 +240,6 @@ protected void AddParameters(IDbCommand command, SqlMapper.Identity identity) ...@@ -249,7 +240,6 @@ protected void AddParameters(IDbCommand command, SqlMapper.Identity identity)
} }
else else
{ {
bool add = !command.Parameters.Contains(name); bool add = !command.Parameters.Contains(name);
IDbDataParameter p; IDbDataParameter p;
if (add) if (add)
...@@ -307,7 +297,6 @@ protected void AddParameters(IDbCommand command, SqlMapper.Identity identity) ...@@ -307,7 +297,6 @@ protected void AddParameters(IDbCommand command, SqlMapper.Identity identity)
/// </summary> /// </summary>
public IEnumerable<string> ParameterNames => parameters.Select(p => p.Key); public IEnumerable<string> ParameterNames => parameters.Select(p => p.Key);
/// <summary> /// <summary>
/// Get the value of a parameter /// Get the value of a parameter
/// </summary> /// </summary>
...@@ -349,18 +338,21 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express ...@@ -349,18 +338,21 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express
// Is it even a MemberExpression? // Is it even a MemberExpression?
var lastMemberAccess = expression.Body as MemberExpression; var lastMemberAccess = expression.Body as MemberExpression;
if (lastMemberAccess == null || if (lastMemberAccess == null
(!(lastMemberAccess.Member is PropertyInfo) && || (!(lastMemberAccess.Member is PropertyInfo)
!(lastMemberAccess.Member is FieldInfo))) && !(lastMemberAccess.Member is FieldInfo)))
{ {
if (expression.Body.NodeType == ExpressionType.Convert && if (expression.Body.NodeType == ExpressionType.Convert
expression.Body.Type == typeof(object) && && expression.Body.Type == typeof(object)
((UnaryExpression)expression.Body).Operand is MemberExpression) && ((UnaryExpression)expression.Body).Operand is MemberExpression)
{ {
// It's got to be unboxed // It's got to be unboxed
lastMemberAccess = (MemberExpression)((UnaryExpression)expression.Body).Operand; lastMemberAccess = (MemberExpression)((UnaryExpression)expression.Body).Operand;
} }
else @throw(); else
{
@throw();
}
} }
// Does the chain consist of MemberExpressions leading to a ParameterExpression of type T? // Does the chain consist of MemberExpressions leading to a ParameterExpression of type T?
...@@ -379,14 +371,13 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express ...@@ -379,14 +371,13 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express
var constant = diving?.Expression as ParameterExpression; var constant = diving?.Expression as ParameterExpression;
diving = diving?.Expression as MemberExpression; diving = diving?.Expression as MemberExpression;
if (constant != null && if (constant != null && constant.Type == typeof(T))
constant.Type == typeof(T))
{ {
break; break;
} }
else if (diving == null || else if (diving == null
(!(diving.Member is PropertyInfo) && || (!(diving.Member is PropertyInfo)
!(diving.Member is FieldInfo))) && !(diving.Member is FieldInfo)))
{ {
@throw(); @throw();
} }
...@@ -422,7 +413,7 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express ...@@ -422,7 +413,7 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express
} }
else // Else it must be a field! else // Else it must be a field!
{ {
il.Emit(OpCodes.Ldfld, ((FieldInfo)member)); // [Member{i}] il.Emit(OpCodes.Ldfld, (FieldInfo)member); // [Member{i}]
} }
} }
...@@ -441,7 +432,7 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express ...@@ -441,7 +432,7 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express
} }
else else
{ {
il.Emit(OpCodes.Stfld, ((FieldInfo)lastMember)); // SET il.Emit(OpCodes.Stfld, (FieldInfo)lastMember); // SET
} }
il.Emit(OpCodes.Ret); // GO il.Emit(OpCodes.Ret); // GO
...@@ -457,11 +448,10 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express ...@@ -457,11 +448,10 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express
(outputCallbacks ?? (outputCallbacks = new List<Action>())).Add(() => (outputCallbacks ?? (outputCallbacks = new List<Action>())).Add(() =>
{ {
// Finally, prep the parameter and attach the callback to it // 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; int sizeToSet = (!size.HasValue && targetMemberType == typeof(string)) ? DbString.DefaultLength : size ?? 0;
if (parameters.TryGetValue(dynamicParamName, out parameter)) if (parameters.TryGetValue(dynamicParamName, out ParamInfo parameter))
{ {
parameter.ParameterDirection = parameter.AttachedParam.Direction = ParameterDirection.InputOutput; parameter.ParameterDirection = parameter.AttachedParam.Direction = ParameterDirection.InputOutput;
...@@ -472,10 +462,9 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express ...@@ -472,10 +462,9 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express
} }
else else
{ {
SqlMapper.ITypeHandler handler;
dbType = (!dbType.HasValue) dbType = (!dbType.HasValue)
#pragma warning disable 618 #pragma warning disable 618
? SqlMapper.LookupDbType(targetMemberType, targetMemberType?.Name, true, out handler) ? SqlMapper.LookupDbType(targetMemberType, targetMemberType?.Name, true, out SqlMapper.ITypeHandler handler)
#pragma warning restore 618 #pragma warning restore 618
: dbType; : dbType;
...@@ -496,7 +485,7 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express ...@@ -496,7 +485,7 @@ public DynamicParameters Output<T>(T target, Expression<Func<T, object>> express
void SqlMapper.IParameterCallbacks.OnCompleted() void SqlMapper.IParameterCallbacks.OnCompleted()
{ {
foreach (var param in (from p in parameters select p.Value)) foreach (var param in from p in parameters select p.Value)
{ {
param.OutputCallback?.Invoke(param.OutputTarget, this); param.OutputCallback?.Invoke(param.OutputTarget, this);
} }
......
...@@ -6,7 +6,7 @@ namespace Dapper ...@@ -6,7 +6,7 @@ namespace Dapper
/// <summary> /// <summary>
/// Handles variances in features per DBMS /// Handles variances in features per DBMS
/// </summary> /// </summary>
class FeatureSupport internal class FeatureSupport
{ {
private static readonly FeatureSupport private static readonly FeatureSupport
Default = new FeatureSupport(false), Default = new FeatureSupport(false),
...@@ -21,6 +21,7 @@ public static FeatureSupport Get(IDbConnection connection) ...@@ -21,6 +21,7 @@ public static FeatureSupport Get(IDbConnection connection)
if (string.Equals(name, "npgsqlconnection", StringComparison.OrdinalIgnoreCase)) return Postgres; if (string.Equals(name, "npgsqlconnection", StringComparison.OrdinalIgnoreCase)) return Postgres;
return Default; return Default;
} }
private FeatureSupport(bool arrays) private FeatureSupport(bool arrays)
{ {
Arrays = arrays; Arrays = arrays;
......
...@@ -6,7 +6,7 @@ namespace Dapper ...@@ -6,7 +6,7 @@ namespace Dapper
/// <summary> /// <summary>
/// Represents simple member map for one of target parameter or property or field to source DataReader column /// Represents simple member map for one of target parameter or property or field to source DataReader column
/// </summary> /// </summary>
sealed class SimpleMemberMap : SqlMapper.IMemberMap internal sealed class SimpleMemberMap : SqlMapper.IMemberMap
{ {
/// <summary> /// <summary>
/// Creates instance for simple property mapping /// Creates instance for simple property mapping
...@@ -15,14 +15,8 @@ sealed class SimpleMemberMap : SqlMapper.IMemberMap ...@@ -15,14 +15,8 @@ sealed class SimpleMemberMap : SqlMapper.IMemberMap
/// <param name="property">Target property</param> /// <param name="property">Target property</param>
public SimpleMemberMap(string columnName, PropertyInfo property) public SimpleMemberMap(string columnName, PropertyInfo property)
{ {
if (columnName == null) ColumnName = columnName ?? throw new ArgumentNullException(nameof(columnName));
throw new ArgumentNullException(nameof(columnName)); Property = property ?? throw new ArgumentNullException(nameof(property));
if (property == null)
throw new ArgumentNullException(nameof(property));
ColumnName = columnName;
Property = property;
} }
/// <summary> /// <summary>
...@@ -32,14 +26,8 @@ public SimpleMemberMap(string columnName, PropertyInfo property) ...@@ -32,14 +26,8 @@ public SimpleMemberMap(string columnName, PropertyInfo property)
/// <param name="field">Target property</param> /// <param name="field">Target property</param>
public SimpleMemberMap(string columnName, FieldInfo field) public SimpleMemberMap(string columnName, FieldInfo field)
{ {
if (columnName == null) ColumnName = columnName ?? throw new ArgumentNullException(nameof(columnName));
throw new ArgumentNullException(nameof(columnName)); Field = field ?? throw new ArgumentNullException(nameof(field));
if (field == null)
throw new ArgumentNullException(nameof(field));
ColumnName = columnName;
Field = field;
} }
/// <summary> /// <summary>
...@@ -49,14 +37,8 @@ public SimpleMemberMap(string columnName, FieldInfo field) ...@@ -49,14 +37,8 @@ public SimpleMemberMap(string columnName, FieldInfo field)
/// <param name="parameter">Target constructor parameter</param> /// <param name="parameter">Target constructor parameter</param>
public SimpleMemberMap(string columnName, ParameterInfo parameter) public SimpleMemberMap(string columnName, ParameterInfo parameter)
{ {
if (columnName == null) ColumnName = columnName ?? throw new ArgumentNullException(nameof(columnName));
throw new ArgumentNullException(nameof(columnName)); Parameter = parameter ?? throw new ArgumentNullException(nameof(parameter));
if (parameter == null)
throw new ArgumentNullException(nameof(parameter));
ColumnName = columnName;
Parameter = parameter;
} }
/// <summary> /// <summary>
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#if !COREFX #if !COREFX
namespace Dapper namespace Dapper
{ {
sealed class SqlDataRecordHandler : SqlMapper.ITypeHandler internal sealed class SqlDataRecordHandler : SqlMapper.ITypeHandler
{ {
public object Parse(Type destinationType, object value) public object Parse(Type destinationType, object value)
{ {
......
...@@ -8,7 +8,7 @@ namespace Dapper ...@@ -8,7 +8,7 @@ namespace Dapper
/// <summary> /// <summary>
/// Used to pass a IEnumerable&lt;SqlDataRecord&gt; as a SqlDataRecordListTVPParameter /// Used to pass a IEnumerable&lt;SqlDataRecord&gt; as a SqlDataRecordListTVPParameter
/// </summary> /// </summary>
sealed class SqlDataRecordListTVPParameter : SqlMapper.ICustomQueryParameter internal sealed class SqlDataRecordListTVPParameter : SqlMapper.ICustomQueryParameter
{ {
private readonly IEnumerable<Microsoft.SqlServer.Server.SqlDataRecord> data; private readonly IEnumerable<Microsoft.SqlServer.Server.SqlDataRecord> data;
private readonly string typeName; private readonly string typeName;
...@@ -20,7 +20,9 @@ public SqlDataRecordListTVPParameter(IEnumerable<Microsoft.SqlServer.Server.SqlD ...@@ -20,7 +20,9 @@ public SqlDataRecordListTVPParameter(IEnumerable<Microsoft.SqlServer.Server.SqlD
this.data = data; this.data = data;
this.typeName = typeName; this.typeName = typeName;
} }
static readonly Action<System.Data.SqlClient.SqlParameter, string> setTypeName;
private static readonly Action<System.Data.SqlClient.SqlParameter, string> setTypeName;
static SqlDataRecordListTVPParameter() static SqlDataRecordListTVPParameter()
{ {
var prop = typeof(System.Data.SqlClient.SqlParameter).GetProperty(nameof(System.Data.SqlClient.SqlParameter.TypeName), BindingFlags.Instance | BindingFlags.Public); var prop = typeof(System.Data.SqlClient.SqlParameter).GetProperty(nameof(System.Data.SqlClient.SqlParameter.TypeName), BindingFlags.Instance | BindingFlags.Public);
...@@ -30,6 +32,7 @@ static SqlDataRecordListTVPParameter() ...@@ -30,6 +32,7 @@ static SqlDataRecordListTVPParameter()
Delegate.CreateDelegate(typeof(Action<System.Data.SqlClient.SqlParameter, string>), prop.GetSetMethod()); Delegate.CreateDelegate(typeof(Action<System.Data.SqlClient.SqlParameter, string>), prop.GetSetMethod());
} }
} }
void SqlMapper.ICustomQueryParameter.AddParameter(IDbCommand command, string name) void SqlMapper.ICustomQueryParameter.AddParameter(IDbCommand command, string name)
{ {
var param = command.CreateParameter(); var param = command.CreateParameter();
...@@ -37,11 +40,11 @@ void SqlMapper.ICustomQueryParameter.AddParameter(IDbCommand command, string nam ...@@ -37,11 +40,11 @@ void SqlMapper.ICustomQueryParameter.AddParameter(IDbCommand command, string nam
Set(param, data, typeName); Set(param, data, typeName);
command.Parameters.Add(param); command.Parameters.Add(param);
} }
internal static void Set(IDbDataParameter parameter, IEnumerable<Microsoft.SqlServer.Server.SqlDataRecord> data, string typeName) internal static void Set(IDbDataParameter parameter, IEnumerable<Microsoft.SqlServer.Server.SqlDataRecord> data, string typeName)
{ {
parameter.Value = (object)data ?? DBNull.Value; parameter.Value = (object)data ?? DBNull.Value;
var sqlParam = parameter as System.Data.SqlClient.SqlParameter; if (parameter is System.Data.SqlClient.SqlParameter sqlParam)
if (sqlParam != null)
{ {
sqlParam.SqlDbType = SqlDbType.Structured; sqlParam.SqlDbType = SqlDbType.Structured;
sqlParam.TypeName = typeName; sqlParam.TypeName = typeName;
......
...@@ -224,6 +224,7 @@ private static Task<DbDataReader> ExecuteReaderWithFlagsFallbackAsync(DbCommand ...@@ -224,6 +224,7 @@ private static Task<DbDataReader> ExecuteReaderWithFlagsFallbackAsync(DbCommand
} }
return task; return task;
} }
private static async Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn, Type effectiveType, CommandDefinition command) private static async Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn, Type effectiveType, CommandDefinition command)
{ {
object param = command.Parameters; object param = command.Parameters;
...@@ -282,10 +283,10 @@ private static async Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn, ...@@ -282,10 +283,10 @@ private static async Task<IEnumerable<T>> QueryAsync<T>(this IDbConnection cnn,
{ {
using (reader) { } // dispose if non-null using (reader) { } // dispose if non-null
if (wasClosed) cnn.Close(); if (wasClosed) cnn.Close();
} }
} }
} }
private static async Task<T> QueryRowAsync<T>(this IDbConnection cnn, Row row, Type effectiveType, CommandDefinition command) private static async Task<T> QueryRowAsync<T>(this IDbConnection cnn, Row row, Type effectiveType, CommandDefinition command)
{ {
object param = command.Parameters; object param = command.Parameters;
...@@ -379,6 +380,7 @@ public AsyncExecState(DbCommand command, Task<int> task) ...@@ -379,6 +380,7 @@ public AsyncExecState(DbCommand command, Task<int> task)
Task = task; Task = task;
} }
} }
private static async Task<int> ExecuteMultiImplAsync(IDbConnection cnn, CommandDefinition command, IEnumerable multiExec) private static async Task<int> ExecuteMultiImplAsync(IDbConnection cnn, CommandDefinition command, IEnumerable multiExec)
{ {
bool isFirst = true; bool isFirst = true;
...@@ -472,6 +474,7 @@ private static async Task<int> ExecuteMultiImplAsync(IDbConnection cnn, CommandD ...@@ -472,6 +474,7 @@ private static async Task<int> ExecuteMultiImplAsync(IDbConnection cnn, CommandD
} }
return total; return total;
} }
private static async Task<int> ExecuteImplAsync(IDbConnection cnn, CommandDefinition command, object param) private static async Task<int> ExecuteImplAsync(IDbConnection cnn, CommandDefinition command, object param)
{ {
var identity = new Identity(command.CommandText, command.CommandType, cnn, null, param?.GetType(), null); var identity = new Identity(command.CommandText, command.CommandType, cnn, null, param?.GetType(), null);
...@@ -785,10 +788,10 @@ public static async Task<GridReader> QueryMultipleAsync(this IDbConnection cnn, ...@@ -785,10 +788,10 @@ public static async Task<GridReader> QueryMultipleAsync(this IDbConnection cnn,
if (reader != null) if (reader != null)
{ {
if (!reader.IsClosed) if (!reader.IsClosed)
try {
{ cmd.Cancel(); } try { cmd.Cancel(); }
catch catch { /* don't spoil the existing exception */ }
{ /* don't spoil the existing exception */ } }
reader.Dispose(); reader.Dispose();
} }
cmd?.Dispose(); cmd?.Dispose();
...@@ -797,7 +800,6 @@ public static async Task<GridReader> QueryMultipleAsync(this IDbConnection cnn, ...@@ -797,7 +800,6 @@ public static async Task<GridReader> QueryMultipleAsync(this IDbConnection cnn,
} }
} }
/// <summary> /// <summary>
/// Execute parameterized SQL and return an <see cref="IDataReader"/> /// Execute parameterized SQL and return an <see cref="IDataReader"/>
/// </summary> /// </summary>
...@@ -859,7 +861,6 @@ private static async Task<IDataReader> ExecuteReaderImplAsync(IDbConnection cnn, ...@@ -859,7 +861,6 @@ private static async Task<IDataReader> ExecuteReaderImplAsync(IDbConnection cnn,
} }
} }
/// <summary> /// <summary>
/// Execute parameterized SQL that selects a single value /// Execute parameterized SQL that selects a single value
/// </summary> /// </summary>
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
class CacheInfo private class CacheInfo
{ {
public DeserializerState Deserializer { get; set; } public DeserializerState Deserializer { get; set; }
public Func<IDataReader, object>[] OtherDeserializers { get; set; } public Func<IDataReader, object>[] OtherDeserializers { get; set; }
......
...@@ -5,27 +5,27 @@ ...@@ -5,27 +5,27 @@
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
private sealed class DapperRow private sealed class DapperRow
: System.Dynamic.IDynamicMetaObjectProvider : System.Dynamic.IDynamicMetaObjectProvider
, IDictionary<string, object> , IDictionary<string, object>
{ {
readonly DapperTable table; private readonly DapperTable table;
object[] values; private object[] values;
public DapperRow(DapperTable table, object[] values) public DapperRow(DapperTable table, object[] values)
{ {
if (table == null) throw new ArgumentNullException(nameof(table)); this.table = table ?? throw new ArgumentNullException(nameof(table));
if (values == null) throw new ArgumentNullException(nameof(values)); this.values = values ?? throw new ArgumentNullException(nameof(values));
this.table = table;
this.values = values;
} }
private sealed class DeadValue private sealed class DeadValue
{ {
public static readonly DeadValue Default = new DeadValue(); public static readonly DeadValue Default = new DeadValue();
private DeadValue() { } private DeadValue() { }
} }
int ICollection<KeyValuePair<string, object>>.Count int ICollection<KeyValuePair<string, object>>.Count
{ {
get get
...@@ -117,8 +117,7 @@ IEnumerator IEnumerable.GetEnumerator() ...@@ -117,8 +117,7 @@ IEnumerator IEnumerable.GetEnumerator()
bool ICollection<KeyValuePair<string, object>>.Contains(KeyValuePair<string, object> item) bool ICollection<KeyValuePair<string, object>>.Contains(KeyValuePair<string, object> item)
{ {
object value; return TryGetValue(item.Key, out object value) && Equals(value, item.Value);
return TryGetValue(item.Key, out value) && Equals(value, item.Value);
} }
void ICollection<KeyValuePair<string, object>>.CopyTo(KeyValuePair<string, object>[] array, int arrayIndex) void ICollection<KeyValuePair<string, object>>.CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
...@@ -162,7 +161,7 @@ IEnumerator IEnumerable.GetEnumerator() ...@@ -162,7 +161,7 @@ IEnumerator IEnumerable.GetEnumerator()
object IDictionary<string, object>.this[string key] object IDictionary<string, object>.this[string key]
{ {
get { object val; TryGetValue(key, out val); return val; } get { TryGetValue(key, out object val); return val; }
set { SetValue(key, value, false); } set { SetValue(key, value, false); }
} }
......
...@@ -3,12 +3,12 @@ ...@@ -3,12 +3,12 @@
using System.Reflection; using System.Reflection;
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
sealed class DapperRowMetaObject : System.Dynamic.DynamicMetaObject private sealed class DapperRowMetaObject : System.Dynamic.DynamicMetaObject
{ {
static readonly MethodInfo getValueMethod = typeof(IDictionary<string, object>).GetProperty("Item").GetGetMethod(); private static readonly MethodInfo getValueMethod = typeof(IDictionary<string, object>).GetProperty("Item").GetGetMethod();
static readonly MethodInfo setValueMethod = typeof(DapperRow).GetMethod("SetValue", new Type[] { typeof(string), typeof(object) }); private static readonly MethodInfo setValueMethod = typeof(DapperRow).GetMethod("SetValue", new Type[] { typeof(string), typeof(object) });
public DapperRowMetaObject( public DapperRowMetaObject(
System.Linq.Expressions.Expression expression, System.Linq.Expressions.Expression expression,
...@@ -27,7 +27,7 @@ object value ...@@ -27,7 +27,7 @@ object value
{ {
} }
System.Dynamic.DynamicMetaObject CallMethod( private System.Dynamic.DynamicMetaObject CallMethod(
MethodInfo method, MethodInfo method,
System.Linq.Expressions.Expression[] parameters System.Linq.Expressions.Expression[] parameters
) )
......
...@@ -3,19 +3,18 @@ ...@@ -3,19 +3,18 @@
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
private sealed class DapperTable private sealed class DapperTable
{ {
string[] fieldNames; private string[] fieldNames;
readonly Dictionary<string, int> fieldNameLookup; private readonly Dictionary<string, int> fieldNameLookup;
internal string[] FieldNames => fieldNames; internal string[] FieldNames => fieldNames;
public DapperTable(string[] fieldNames) public DapperTable(string[] fieldNames)
{ {
if (fieldNames == null) throw new ArgumentNullException(nameof(fieldNames)); this.fieldNames = fieldNames ?? throw new ArgumentNullException(nameof(fieldNames));
this.fieldNames = fieldNames;
fieldNameLookup = new Dictionary<string, int>(fieldNames.Length, StringComparer.Ordinal); fieldNameLookup = new Dictionary<string, int>(fieldNames.Length, StringComparer.Ordinal);
// if there are dups, we want the **first** key to be the "winner" - so iterate backwards // if there are dups, we want the **first** key to be the "winner" - so iterate backwards
...@@ -28,9 +27,9 @@ public DapperTable(string[] fieldNames) ...@@ -28,9 +27,9 @@ public DapperTable(string[] fieldNames)
internal int IndexOfName(string name) internal int IndexOfName(string name)
{ {
int result; return (name != null && fieldNameLookup.TryGetValue(name, out int result)) ? result : -1;
return (name != null && fieldNameLookup.TryGetValue(name, out result)) ? result : -1;
} }
internal int AddField(string name) internal int AddField(string name)
{ {
if (name == null) throw new ArgumentNullException(nameof(name)); if (name == null) throw new ArgumentNullException(nameof(name));
......
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
struct DeserializerState private struct DeserializerState
{ {
public readonly int Hash; public readonly int Hash;
public readonly Func<IDataReader, object> Func; public readonly Func<IDataReader, object> Func;
......
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
/// <summary> /// <summary>
/// Dummy type for excluding from multi-map /// Dummy type for excluding from multi-map
/// </summary> /// </summary>
class DontMap { } private class DontMap { }
} }
} }
...@@ -9,11 +9,11 @@ ...@@ -9,11 +9,11 @@
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
partial class GridReader public partial class GridReader
{ {
CancellationToken cancel; private readonly CancellationToken cancel;
internal GridReader(IDbCommand command, IDataReader reader, Identity identity, DynamicParameters dynamicParams, bool addToCache, CancellationToken cancel) internal GridReader(IDbCommand command, IDataReader reader, Identity identity, DynamicParameters dynamicParams, bool addToCache, CancellationToken cancel)
: this(command, reader, identity, dynamicParams, addToCache) : this(command, reader, identity, dynamicParams, addToCache)
{ {
...@@ -37,6 +37,7 @@ public Task<dynamic> ReadFirstAsync() ...@@ -37,6 +37,7 @@ public Task<dynamic> ReadFirstAsync()
{ {
return ReadRowAsyncImpl<dynamic>(typeof(DapperRow), Row.First); return ReadRowAsyncImpl<dynamic>(typeof(DapperRow), Row.First);
} }
/// <summary> /// <summary>
/// Read an individual row of the next grid of results, returned as a dynamic object /// Read an individual row of the next grid of results, returned as a dynamic object
/// </summary> /// </summary>
...@@ -45,6 +46,7 @@ public Task<dynamic> ReadFirstOrDefaultAsync() ...@@ -45,6 +46,7 @@ public Task<dynamic> ReadFirstOrDefaultAsync()
{ {
return ReadRowAsyncImpl<dynamic>(typeof(DapperRow), Row.FirstOrDefault); return ReadRowAsyncImpl<dynamic>(typeof(DapperRow), Row.FirstOrDefault);
} }
/// <summary> /// <summary>
/// Read an individual row of the next grid of results, returned as a dynamic object /// Read an individual row of the next grid of results, returned as a dynamic object
/// </summary> /// </summary>
...@@ -53,6 +55,7 @@ public Task<dynamic> ReadSingleAsync() ...@@ -53,6 +55,7 @@ public Task<dynamic> ReadSingleAsync()
{ {
return ReadRowAsyncImpl<dynamic>(typeof(DapperRow), Row.Single); return ReadRowAsyncImpl<dynamic>(typeof(DapperRow), Row.Single);
} }
/// <summary> /// <summary>
/// Read an individual row of the next grid of results, returned as a dynamic object /// Read an individual row of the next grid of results, returned as a dynamic object
/// </summary> /// </summary>
...@@ -79,6 +82,7 @@ public Task<object> ReadFirstAsync(Type type) ...@@ -79,6 +82,7 @@ public Task<object> ReadFirstAsync(Type type)
if (type == null) throw new ArgumentNullException(nameof(type)); if (type == null) throw new ArgumentNullException(nameof(type));
return ReadRowAsyncImpl<object>(type, Row.First); return ReadRowAsyncImpl<object>(type, Row.First);
} }
/// <summary> /// <summary>
/// Read an individual row of the next grid of results /// Read an individual row of the next grid of results
/// </summary> /// </summary>
...@@ -87,6 +91,7 @@ public Task<object> ReadFirstOrDefaultAsync(Type type) ...@@ -87,6 +91,7 @@ public Task<object> ReadFirstOrDefaultAsync(Type type)
if (type == null) throw new ArgumentNullException(nameof(type)); if (type == null) throw new ArgumentNullException(nameof(type));
return ReadRowAsyncImpl<object>(type, Row.FirstOrDefault); return ReadRowAsyncImpl<object>(type, Row.FirstOrDefault);
} }
/// <summary> /// <summary>
/// Read an individual row of the next grid of results /// Read an individual row of the next grid of results
/// </summary> /// </summary>
...@@ -95,6 +100,7 @@ public Task<object> ReadSingleAsync(Type type) ...@@ -95,6 +100,7 @@ public Task<object> ReadSingleAsync(Type type)
if (type == null) throw new ArgumentNullException(nameof(type)); if (type == null) throw new ArgumentNullException(nameof(type));
return ReadRowAsyncImpl<object>(type, Row.Single); return ReadRowAsyncImpl<object>(type, Row.Single);
} }
/// <summary> /// <summary>
/// Read an individual row of the next grid of results /// Read an individual row of the next grid of results
/// </summary> /// </summary>
...@@ -119,6 +125,7 @@ public Task<T> ReadFirstAsync<T>() ...@@ -119,6 +125,7 @@ public Task<T> ReadFirstAsync<T>()
{ {
return ReadRowAsyncImpl<T>(typeof(T), Row.First); return ReadRowAsyncImpl<T>(typeof(T), Row.First);
} }
/// <summary> /// <summary>
/// Read an individual row of the next grid of results /// Read an individual row of the next grid of results
/// </summary> /// </summary>
...@@ -126,6 +133,7 @@ public Task<T> ReadFirstOrDefaultAsync<T>() ...@@ -126,6 +133,7 @@ public Task<T> ReadFirstOrDefaultAsync<T>()
{ {
return ReadRowAsyncImpl<T>(typeof(T), Row.FirstOrDefault); return ReadRowAsyncImpl<T>(typeof(T), Row.FirstOrDefault);
} }
/// <summary> /// <summary>
/// Read an individual row of the next grid of results /// Read an individual row of the next grid of results
/// </summary> /// </summary>
...@@ -133,6 +141,7 @@ public Task<T> ReadSingleAsync<T>() ...@@ -133,6 +141,7 @@ public Task<T> ReadSingleAsync<T>()
{ {
return ReadRowAsyncImpl<T>(typeof(T), Row.Single); return ReadRowAsyncImpl<T>(typeof(T), Row.Single);
} }
/// <summary> /// <summary>
/// Read an individual row of the next grid of results /// Read an individual row of the next grid of results
/// </summary> /// </summary>
...@@ -189,8 +198,7 @@ private Task<IEnumerable<T>> ReadAsyncImpl<T>(Type type, bool buffered) ...@@ -189,8 +198,7 @@ private Task<IEnumerable<T>> ReadAsyncImpl<T>(Type type, bool buffered)
private Task<T> ReadRowAsyncImpl<T>(Type type, Row row) private Task<T> ReadRowAsyncImpl<T>(Type type, Row row)
{ {
var dbReader = reader as DbDataReader; if (reader is DbDataReader dbReader) return ReadRowAsyncImplViaDbReader<T>(dbReader, type, row);
if (dbReader != null) return ReadRowAsyncImplViaDbReader<T>(dbReader, type, row);
// no async API available; use non-async and fake it // no async API available; use non-async and fake it
return Task.FromResult<T>(ReadRow<T>(type, row)); return Task.FromResult<T>(ReadRow<T>(type, row));
...@@ -232,7 +240,7 @@ private async Task<IEnumerable<T>> ReadBufferedAsync<T>(int index, Func<IDataRea ...@@ -232,7 +240,7 @@ private async Task<IEnumerable<T>> ReadBufferedAsync<T>(int index, Func<IDataRea
try try
{ {
var reader = (DbDataReader)this.reader; var reader = (DbDataReader)this.reader;
List<T> buffer = new List<T>(); var buffer = new List<T>();
while (index == gridIndex && await reader.ReadAsync(cancel).ConfigureAwait(false)) while (index == gridIndex && await reader.ReadAsync(cancel).ConfigureAwait(false))
{ {
buffer.Add((T)deserializer(reader)); buffer.Add((T)deserializer(reader));
...@@ -248,7 +256,6 @@ private async Task<IEnumerable<T>> ReadBufferedAsync<T>(int index, Func<IDataRea ...@@ -248,7 +256,6 @@ private async Task<IEnumerable<T>> ReadBufferedAsync<T>(int index, Func<IDataRea
} }
} }
} }
} }
} }
#endif #endif
\ No newline at end of file
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
using System.Globalization; using System.Globalization;
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
/// <summary> /// <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
...@@ -13,8 +13,8 @@ partial class SqlMapper ...@@ -13,8 +13,8 @@ partial class SqlMapper
public partial class GridReader : IDisposable public partial class GridReader : IDisposable
{ {
private IDataReader reader; private IDataReader reader;
private Identity identity; private readonly Identity identity;
private bool addToCache; private readonly bool addToCache;
internal GridReader(IDbCommand command, IDataReader reader, Identity identity, IParameterCallbacks callbacks, bool addToCache) internal GridReader(IDbCommand command, IDataReader reader, Identity identity, IParameterCallbacks callbacks, bool addToCache)
{ {
...@@ -29,80 +29,66 @@ internal GridReader(IDbCommand command, IDataReader reader, Identity identity, I ...@@ -29,80 +29,66 @@ internal GridReader(IDbCommand command, IDataReader reader, Identity identity, I
/// Read the next grid of results, returned as a dynamic object /// Read the next grid of results, returned as a dynamic object
/// </summary> /// </summary>
/// <remarks>Note: each row can be accessed via "dynamic", or by casting to an IDictionary&lt;string,object&gt;</remarks> /// <remarks>Note: each row can be accessed via "dynamic", or by casting to an IDictionary&lt;string,object&gt;</remarks>
public IEnumerable<dynamic> Read(bool buffered = true) public IEnumerable<dynamic> Read(bool buffered = true) =>
{ ReadImpl<dynamic>(typeof(DapperRow), buffered);
return ReadImpl<dynamic>(typeof(DapperRow), buffered);
}
/// <summary> /// <summary>
/// Read an individual row of the next grid of results, returned as a dynamic object /// Read an individual row of the next grid of results, returned as a dynamic object
/// </summary> /// </summary>
/// <remarks>Note: the row can be accessed via "dynamic", or by casting to an IDictionary&lt;string,object&gt;</remarks> /// <remarks>Note: the row can be accessed via "dynamic", or by casting to an IDictionary&lt;string,object&gt;</remarks>
public dynamic ReadFirst() public dynamic ReadFirst() =>
{ ReadRow<dynamic>(typeof(DapperRow), Row.First);
return ReadRow<dynamic>(typeof(DapperRow), Row.First);
}
/// <summary> /// <summary>
/// Read an individual row of the next grid of results, returned as a dynamic object /// Read an individual row of the next grid of results, returned as a dynamic object
/// </summary> /// </summary>
/// <remarks>Note: the row can be accessed via "dynamic", or by casting to an IDictionary&lt;string,object&gt;</remarks> /// <remarks>Note: the row can be accessed via "dynamic", or by casting to an IDictionary&lt;string,object&gt;</remarks>
public dynamic ReadFirstOrDefault() public dynamic ReadFirstOrDefault() =>
{ ReadRow<dynamic>(typeof(DapperRow), Row.FirstOrDefault);
return ReadRow<dynamic>(typeof(DapperRow), Row.FirstOrDefault);
}
/// <summary> /// <summary>
/// Read an individual row of the next grid of results, returned as a dynamic object /// Read an individual row of the next grid of results, returned as a dynamic object
/// </summary> /// </summary>
/// <remarks>Note: the row can be accessed via "dynamic", or by casting to an IDictionary&lt;string,object&gt;</remarks> /// <remarks>Note: the row can be accessed via "dynamic", or by casting to an IDictionary&lt;string,object&gt;</remarks>
public dynamic ReadSingle() public dynamic ReadSingle() =>
{ ReadRow<dynamic>(typeof(DapperRow), Row.Single);
return ReadRow<dynamic>(typeof(DapperRow), Row.Single);
}
/// <summary> /// <summary>
/// Read an individual row of the next grid of results, returned as a dynamic object /// Read an individual row of the next grid of results, returned as a dynamic object
/// </summary> /// </summary>
/// <remarks>Note: the row can be accessed via "dynamic", or by casting to an IDictionary&lt;string,object&gt;</remarks> /// <remarks>Note: the row can be accessed via "dynamic", or by casting to an IDictionary&lt;string,object&gt;</remarks>
public dynamic ReadSingleOrDefault() public dynamic ReadSingleOrDefault() =>
{ ReadRow<dynamic>(typeof(DapperRow), Row.SingleOrDefault);
return ReadRow<dynamic>(typeof(DapperRow), Row.SingleOrDefault);
}
/// <summary> /// <summary>
/// Read the next grid of results /// Read the next grid of results
/// </summary> /// </summary>
public IEnumerable<T> Read<T>(bool buffered = true) public IEnumerable<T> Read<T>(bool buffered = true) =>
{ ReadImpl<T>(typeof(T), buffered);
return ReadImpl<T>(typeof(T), buffered);
}
/// <summary> /// <summary>
/// Read an individual row of the next grid of results /// Read an individual row of the next grid of results
/// </summary> /// </summary>
public T ReadFirst<T>() public T ReadFirst<T>() =>
{ ReadRow<T>(typeof(T), Row.First);
return ReadRow<T>(typeof(T), Row.First);
}
/// <summary> /// <summary>
/// Read an individual row of the next grid of results /// Read an individual row of the next grid of results
/// </summary> /// </summary>
public T ReadFirstOrDefault<T>() public T ReadFirstOrDefault<T>() =>
{ ReadRow<T>(typeof(T), Row.FirstOrDefault);
return ReadRow<T>(typeof(T), Row.FirstOrDefault);
}
/// <summary> /// <summary>
/// Read an individual row of the next grid of results /// Read an individual row of the next grid of results
/// </summary> /// </summary>
public T ReadSingle<T>() public T ReadSingle<T>() =>
{ ReadRow<T>(typeof(T), Row.Single);
return ReadRow<T>(typeof(T), Row.Single);
}
/// <summary> /// <summary>
/// Read an individual row of the next grid of results /// Read an individual row of the next grid of results
/// </summary> /// </summary>
public T ReadSingleOrDefault<T>() public T ReadSingleOrDefault<T>() =>
{ ReadRow<T>(typeof(T), Row.SingleOrDefault);
return ReadRow<T>(typeof(T), Row.SingleOrDefault);
}
/// <summary> /// <summary>
/// Read the next grid of results /// Read the next grid of results
...@@ -121,6 +107,7 @@ public object ReadFirst(Type type) ...@@ -121,6 +107,7 @@ public object ReadFirst(Type type)
if (type == null) throw new ArgumentNullException(nameof(type)); if (type == null) throw new ArgumentNullException(nameof(type));
return ReadRow<object>(type, Row.First); return ReadRow<object>(type, Row.First);
} }
/// <summary> /// <summary>
/// Read an individual row of the next grid of results /// Read an individual row of the next grid of results
/// </summary> /// </summary>
...@@ -129,6 +116,7 @@ public object ReadFirstOrDefault(Type type) ...@@ -129,6 +116,7 @@ public object ReadFirstOrDefault(Type type)
if (type == null) throw new ArgumentNullException(nameof(type)); if (type == null) throw new ArgumentNullException(nameof(type));
return ReadRow<object>(type, Row.FirstOrDefault); return ReadRow<object>(type, Row.FirstOrDefault);
} }
/// <summary> /// <summary>
/// Read an individual row of the next grid of results /// Read an individual row of the next grid of results
/// </summary> /// </summary>
...@@ -137,6 +125,7 @@ public object ReadSingle(Type type) ...@@ -137,6 +125,7 @@ public object ReadSingle(Type type)
if (type == null) throw new ArgumentNullException(nameof(type)); if (type == null) throw new ArgumentNullException(nameof(type));
return ReadRow<object>(type, Row.Single); return ReadRow<object>(type, Row.Single);
} }
/// <summary> /// <summary>
/// Read an individual row of the next grid of results /// Read an individual row of the next grid of results
/// </summary> /// </summary>
...@@ -203,7 +192,6 @@ private T ReadRow<T>(Type type, Row row) ...@@ -203,7 +192,6 @@ private T ReadRow<T>(Type type, Row row)
return result; return result;
} }
private IEnumerable<TReturn> MultiReadInternal<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(Delegate func, string splitOn) private IEnumerable<TReturn> MultiReadInternal<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, TSeventh, TReturn>(Delegate func, string splitOn)
{ {
var identity = this.identity.ForGrid(typeof(TReturn), new Type[] { var identity = this.identity.ForGrid(typeof(TReturn), new Type[] {
...@@ -282,6 +270,7 @@ private IEnumerable<TReturn> MultiReadInternal<TReturn>(Type[] types, Func<objec ...@@ -282,6 +270,7 @@ private IEnumerable<TReturn> MultiReadInternal<TReturn>(Type[] types, Func<objec
var result = MultiReadInternal<TFirst, TSecond, TThird, TFourth, TFifth, DontMap, DontMap, TReturn>(func, splitOn); var result = MultiReadInternal<TFirst, TSecond, TThird, TFourth, TFifth, DontMap, DontMap, TReturn>(func, splitOn);
return buffered ? result.ToList() : result; return buffered ? result.ToList() : result;
} }
/// <summary> /// <summary>
/// Read multiple objects from a single record set on the grid /// Read multiple objects from a single record set on the grid
/// </summary> /// </summary>
...@@ -290,6 +279,7 @@ private IEnumerable<TReturn> MultiReadInternal<TReturn>(Type[] types, Func<objec ...@@ -290,6 +279,7 @@ private IEnumerable<TReturn> MultiReadInternal<TReturn>(Type[] types, Func<objec
var result = MultiReadInternal<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, DontMap, TReturn>(func, splitOn); var result = MultiReadInternal<TFirst, TSecond, TThird, TFourth, TFifth, TSixth, DontMap, TReturn>(func, splitOn);
return buffered ? result.ToList() : result; return buffered ? result.ToList() : result;
} }
/// <summary> /// <summary>
/// Read multiple objects from a single record set on the grid /// Read multiple objects from a single record set on the grid
/// </summary> /// </summary>
...@@ -331,8 +321,9 @@ private IEnumerable<T> ReadDeferred<T>(int index, Func<IDataReader, object> dese ...@@ -331,8 +321,9 @@ private IEnumerable<T> ReadDeferred<T>(int index, Func<IDataReader, object> dese
} }
} }
} }
private int gridIndex, readCount; private int gridIndex, readCount;
private IParameterCallbacks callbacks; private readonly IParameterCallbacks callbacks;
/// <summary> /// <summary>
/// Has the underlying reader been consumed? /// Has the underlying reader been consumed?
...@@ -362,6 +353,7 @@ private void NextResult() ...@@ -362,6 +353,7 @@ private void NextResult()
Dispose(); Dispose();
} }
} }
/// <summary> /// <summary>
/// Dispose the grid, closing and disposing both the underlying reader and command. /// Dispose the grid, closing and disposing both the underlying reader and command.
/// </summary> /// </summary>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
/// <summary> /// <summary>
/// Implement this interface to pass an arbitrary db specific parameter to Dapper /// Implement this interface to pass an arbitrary db specific parameter to Dapper
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
/// <summary> /// <summary>
/// Parses a data reader to a sequence of data of the supplied type. Used for deserializing a reader without a connection, etc. /// Parses a data reader to a sequence of data of the supplied type. Used for deserializing a reader without a connection, etc.
...@@ -122,7 +122,7 @@ public static IEnumerable<dynamic> Parse(this IDataReader reader) ...@@ -122,7 +122,7 @@ public static IEnumerable<dynamic> Parse(this IDataReader reader)
public static Func<IDataReader, T> GetRowParser<T>(this IDataReader reader, Type concreteType = null, public static Func<IDataReader, T> GetRowParser<T>(this IDataReader reader, Type concreteType = null,
int startIndex = 0, int length = -1, bool returnNullIfFirstMissing = false) int startIndex = 0, int length = -1, bool returnNullIfFirstMissing = false)
{ {
if (concreteType == null) concreteType = typeof(T); concreteType = concreteType ?? typeof(T);
var func = GetDeserializer(concreteType, reader, startIndex, length, returnNullIfFirstMissing); var func = GetDeserializer(concreteType, reader, startIndex, length, returnNullIfFirstMissing);
if (concreteType.IsValueType()) if (concreteType.IsValueType())
{ {
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
/// <summary> /// <summary>
/// Implement this interface to pass an arbitrary db specific set of parameters to Dapper /// Implement this interface to pass an arbitrary db specific set of parameters to Dapper
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
/// <summary> /// <summary>
/// Implements this interface to provide custom member mapping /// Implements this interface to provide custom member mapping
......
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
/// <summary> /// <summary>
/// Extends IDynamicParameters with facilities for executing callbacks after commands have completed /// Extends IDynamicParameters with facilities for executing callbacks after commands have completed
......
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
/// <summary> /// <summary>
/// Extends IDynamicParameters providing by-name lookup of parameter values /// Extends IDynamicParameters providing by-name lookup of parameter values
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
/// <summary> /// <summary>
/// Implement this interface to perform custom type-based parameter handling and value parsing /// Implement this interface to perform custom type-based parameter handling and value parsing
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
/// <summary> /// <summary>
/// Implement this interface to change default mapping of reader columns to type members /// Implement this interface to change default mapping of reader columns to type members
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
/// <summary> /// <summary>
/// Identity of a cached query in Dapper, used for extensibility /// Identity of a cached query in Dapper, used for extensibility
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
/// <summary> /// <summary>
/// This is a micro-cache; suitable when the number of terms is controllable (a few hundred, for example), /// This is a micro-cache; suitable when the number of terms is controllable (a few hundred, for example),
...@@ -25,14 +25,14 @@ public static bool TryGet(Link<TKey, TValue> link, TKey key, out TValue value) ...@@ -25,14 +25,14 @@ public static bool TryGet(Link<TKey, TValue> link, TKey key, out TValue value)
value = default(TValue); value = default(TValue);
return false; return false;
} }
public static bool TryAdd(ref Link<TKey, TValue> head, TKey key, ref TValue value) public static bool TryAdd(ref Link<TKey, TValue> head, TKey key, ref TValue value)
{ {
bool tryAgain; bool tryAgain;
do do
{ {
var snapshot = Interlocked.CompareExchange(ref head, null, null); var snapshot = Interlocked.CompareExchange(ref head, null, null);
TValue found; if (TryGet(snapshot, key, out TValue found))
if (TryGet(snapshot, key, out found))
{ // existing match; report the existing value instead { // existing match; report the existing value instead
value = found; value = found;
return false; return false;
...@@ -43,12 +43,14 @@ public static bool TryAdd(ref Link<TKey, TValue> head, TKey key, ref TValue valu ...@@ -43,12 +43,14 @@ public static bool TryAdd(ref Link<TKey, TValue> head, TKey key, ref TValue valu
} while (tryAgain); } while (tryAgain);
return true; return true;
} }
private Link(TKey key, TValue value, Link<TKey, TValue> tail) private Link(TKey key, TValue value, Link<TKey, TValue> tail)
{ {
Key = key; Key = key;
Value = value; Value = value;
Tail = tail; Tail = tail;
} }
public TKey Key { get; } public TKey Key { get; }
public TValue Value { get; } public TValue Value { get; }
public Link<TKey, TValue> Tail { get; } public Link<TKey, TValue> Tail { get; }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
/// <summary> /// <summary>
/// Represents a placeholder for a value that should be replaced as a literal value in the resulting sql /// Represents a placeholder for a value that should be replaced as a literal value in the resulting sql
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
/// <summary> /// <summary>
/// Permits specifying certain SqlMapper values globally. /// Permits specifying certain SqlMapper values globally.
...@@ -11,7 +11,7 @@ partial class SqlMapper ...@@ -11,7 +11,7 @@ partial class SqlMapper
public static class Settings public static class Settings
{ {
// disable single result by default; prevents errors AFTER the select being detected properly // disable single result by default; prevents errors AFTER the select being detected properly
const CommandBehavior DefaultAllowedCommandBehaviors = ~CommandBehavior.SingleResult; private const CommandBehavior DefaultAllowedCommandBehaviors = ~CommandBehavior.SingleResult;
internal static CommandBehavior AllowedCommandBehaviors { get; private set; } = DefaultAllowedCommandBehaviors; internal static CommandBehavior AllowedCommandBehaviors { get; private set; } = DefaultAllowedCommandBehaviors;
private static void SetAllowedCommandBehaviors(CommandBehavior behavior, bool enabled) private static void SetAllowedCommandBehaviors(CommandBehavior behavior, bool enabled)
{ {
...@@ -36,6 +36,7 @@ public static bool UseSingleRowOptimization ...@@ -36,6 +36,7 @@ public static bool UseSingleRowOptimization
get { return (AllowedCommandBehaviors & CommandBehavior.SingleRow) != 0; } get { return (AllowedCommandBehaviors & CommandBehavior.SingleRow) != 0; }
set { SetAllowedCommandBehaviors(CommandBehavior.SingleRow, value); } set { SetAllowedCommandBehaviors(CommandBehavior.SingleRow, value); }
} }
internal static bool DisableCommandBehaviorOptimizations(CommandBehavior behavior, Exception ex) internal static bool DisableCommandBehaviorOptimizations(CommandBehavior behavior, Exception ex)
{ {
if (AllowedCommandBehaviors == DefaultAllowedCommandBehaviors if (AllowedCommandBehaviors == DefaultAllowedCommandBehaviors
...@@ -75,7 +76,6 @@ public static void SetDefaults() ...@@ -75,7 +76,6 @@ public static void SetDefaults()
/// </summary> /// </summary>
public static bool ApplyNullValues { get; set; } public static bool ApplyNullValues { get; set; }
/// <summary> /// <summary>
/// Should list expansions be padded with null-valued parameters, to prevent query-plan saturation? For example, /// Should list expansions be padded with null-valued parameters, to prevent query-plan saturation? For example,
/// an 'in @foo' expansion with 7, 8 or 9 values will be sent as a list of 10 values, with 3, 2 or 1 of them null. /// an 'in @foo' expansion with 7, 8 or 9 values will be sent as a list of 10 values, with 3, 2 or 1 of them null.
......
...@@ -6,16 +6,16 @@ ...@@ -6,16 +6,16 @@
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
private class TypeDeserializerCache private class TypeDeserializerCache
{ {
private TypeDeserializerCache(Type type) private TypeDeserializerCache(Type type)
{ {
this.type = type; this.type = type;
} }
static readonly Hashtable byType = new Hashtable();
private static readonly Hashtable byType = new Hashtable();
private readonly Type type; private readonly Type type;
internal static void Purge(Type type) internal static void Purge(Type type)
{ {
...@@ -24,6 +24,7 @@ internal static void Purge(Type type) ...@@ -24,6 +24,7 @@ internal static void Purge(Type type)
byType.Remove(type); byType.Remove(type);
} }
} }
internal static void Purge() internal static void Purge()
{ {
lock (byType) lock (byType)
...@@ -48,8 +49,10 @@ internal static void Purge() ...@@ -48,8 +49,10 @@ internal static void Purge()
} }
return found.GetReader(reader, startBound, length, returnNullIfFirstMissing); return found.GetReader(reader, startBound, length, returnNullIfFirstMissing);
} }
private Dictionary<DeserializerKey, Func<IDataReader, object>> readers = new Dictionary<DeserializerKey, Func<IDataReader, object>>();
struct DeserializerKey : IEquatable<DeserializerKey> private readonly Dictionary<DeserializerKey, Func<IDataReader, object>> readers = new Dictionary<DeserializerKey, Func<IDataReader, object>>();
private struct DeserializerKey : IEquatable<DeserializerKey>
{ {
private readonly int startBound, length; private readonly int startBound, length;
private readonly bool returnNullIfFirstMissing; private readonly bool returnNullIfFirstMissing;
...@@ -85,10 +88,8 @@ public DeserializerKey(int hashCode, int startBound, int length, bool returnNull ...@@ -85,10 +88,8 @@ public DeserializerKey(int hashCode, int startBound, int length, bool returnNull
} }
} }
public override int GetHashCode() public override int GetHashCode() => hashCode;
{
return hashCode;
}
public override string ToString() public override string ToString()
{ // only used in the debugger { // only used in the debugger
if (names != null) if (names != null)
...@@ -108,24 +109,26 @@ public override string ToString() ...@@ -108,24 +109,26 @@ public override string ToString()
} }
return base.ToString(); return base.ToString();
} }
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
return obj is DeserializerKey && Equals((DeserializerKey)obj); return obj is DeserializerKey && Equals((DeserializerKey)obj);
} }
public bool Equals(DeserializerKey other) public bool Equals(DeserializerKey other)
{ {
if (this.hashCode != other.hashCode if (hashCode != other.hashCode
|| this.startBound != other.startBound || startBound != other.startBound
|| this.length != other.length || length != other.length
|| this.returnNullIfFirstMissing != other.returnNullIfFirstMissing) || returnNullIfFirstMissing != other.returnNullIfFirstMissing)
{ {
return false; // clearly different return false; // clearly different
} }
for (int i = 0; i < length; i++) for (int i = 0; i < length; i++)
{ {
if ((this.names?[i] ?? this.reader?.GetName(startBound + i)) != (other.names?[i] ?? other.reader?.GetName(startBound + i)) if ((names?[i] ?? reader?.GetName(startBound + i)) != (other.names?[i] ?? other.reader?.GetName(startBound + i))
|| ||
(this.types?[i] ?? this.reader?.GetFieldType(startBound + i)) != (other.types?[i] ?? other.reader?.GetFieldType(startBound + i)) (types?[i] ?? reader?.GetFieldType(startBound + i)) != (other.types?[i] ?? other.reader?.GetFieldType(startBound + i))
) )
{ {
return false; // different column name or type return false; // different column name or type
...@@ -134,6 +137,7 @@ public bool Equals(DeserializerKey other) ...@@ -134,6 +137,7 @@ public bool Equals(DeserializerKey other)
return true; return true;
} }
} }
private Func<IDataReader, object> GetReader(IDataReader reader, int startBound, int length, bool returnNullIfFirstMissing) private Func<IDataReader, object> GetReader(IDataReader reader, int startBound, int length, bool returnNullIfFirstMissing)
{ {
if (length < 0) length = reader.FieldCount - startBound; if (length < 0) length = reader.FieldCount - startBound;
...@@ -155,6 +159,5 @@ public bool Equals(DeserializerKey other) ...@@ -155,6 +159,5 @@ public bool Equals(DeserializerKey other)
} }
} }
} }
} }
} }
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
/// <summary> /// <summary>
/// Base-class for simple type-handlers /// Base-class for simple type-handlers
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
/// <summary> /// <summary>
/// Not intended for direct usage /// Not intended for direct usage
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ namespace Dapper ...@@ -8,7 +8,7 @@ namespace Dapper
/// <summary> /// <summary>
/// Used to pass a DataTable as a TableValuedParameter /// Used to pass a DataTable as a TableValuedParameter
/// </summary> /// </summary>
sealed class TableValuedParameter : SqlMapper.ICustomQueryParameter internal sealed class TableValuedParameter : SqlMapper.ICustomQueryParameter
{ {
private readonly DataTable table; private readonly DataTable table;
private readonly string typeName; private readonly string typeName;
...@@ -25,7 +25,8 @@ public TableValuedParameter(DataTable table, string typeName) ...@@ -25,7 +25,8 @@ public TableValuedParameter(DataTable table, string typeName)
this.table = table; this.table = table;
this.typeName = typeName; this.typeName = typeName;
} }
static readonly Action<System.Data.SqlClient.SqlParameter, string> setTypeName;
private static readonly Action<System.Data.SqlClient.SqlParameter, string> setTypeName;
static TableValuedParameter() static TableValuedParameter()
{ {
var prop = typeof(System.Data.SqlClient.SqlParameter).GetProperty("TypeName", BindingFlags.Instance | BindingFlags.Public); var prop = typeof(System.Data.SqlClient.SqlParameter).GetProperty("TypeName", BindingFlags.Instance | BindingFlags.Public);
...@@ -35,6 +36,7 @@ static TableValuedParameter() ...@@ -35,6 +36,7 @@ static TableValuedParameter()
Delegate.CreateDelegate(typeof(Action<System.Data.SqlClient.SqlParameter, string>), prop.GetSetMethod()); Delegate.CreateDelegate(typeof(Action<System.Data.SqlClient.SqlParameter, string>), prop.GetSetMethod());
} }
} }
void SqlMapper.ICustomQueryParameter.AddParameter(IDbCommand command, string name) void SqlMapper.ICustomQueryParameter.AddParameter(IDbCommand command, string name)
{ {
var param = command.CreateParameter(); var param = command.CreateParameter();
...@@ -42,6 +44,7 @@ void SqlMapper.ICustomQueryParameter.AddParameter(IDbCommand command, string nam ...@@ -42,6 +44,7 @@ void SqlMapper.ICustomQueryParameter.AddParameter(IDbCommand command, string nam
Set(param, table, typeName); Set(param, table, typeName);
command.Parameters.Add(param); command.Parameters.Add(param);
} }
internal static void Set(IDbDataParameter parameter, DataTable table, string typeName) internal static void Set(IDbDataParameter parameter, DataTable table, string typeName)
{ {
#pragma warning disable 0618 #pragma warning disable 0618
...@@ -53,8 +56,7 @@ internal static void Set(IDbDataParameter parameter, DataTable table, string typ ...@@ -53,8 +56,7 @@ internal static void Set(IDbDataParameter parameter, DataTable table, string typ
} }
if (!string.IsNullOrEmpty(typeName)) if (!string.IsNullOrEmpty(typeName))
{ {
var sqlParam = parameter as System.Data.SqlClient.SqlParameter; if (parameter is System.Data.SqlClient.SqlParameter sqlParam)
if (sqlParam != null)
{ {
setTypeName?.Invoke(sqlParam, typeName); setTypeName?.Invoke(sqlParam, typeName);
sqlParam.SqlDbType = SqlDbType.Structured; sqlParam.SqlDbType = SqlDbType.Structured;
......
...@@ -6,47 +6,41 @@ namespace Dapper ...@@ -6,47 +6,41 @@ namespace Dapper
{ {
internal static class TypeExtensions internal static class TypeExtensions
{ {
public static string Name(this Type type) public static string Name(this Type type) =>
{
#if COREFX #if COREFX
return type.GetTypeInfo().Name; type.GetTypeInfo().Name;
#else #else
return type.Name; type.Name;
#endif #endif
}
public static bool IsValueType(this Type type) public static bool IsValueType(this Type type) =>
{
#if COREFX #if COREFX
return type.GetTypeInfo().IsValueType; type.GetTypeInfo().IsValueType;
#else #else
return type.IsValueType; type.IsValueType;
#endif #endif
}
public static bool IsEnum(this Type type) public static bool IsEnum(this Type type) =>
{
#if COREFX #if COREFX
return type.GetTypeInfo().IsEnum; type.GetTypeInfo().IsEnum;
#else #else
return type.IsEnum; type.IsEnum;
#endif #endif
}
public static bool IsGenericType(this Type type) public static bool IsGenericType(this Type type) =>
{
#if COREFX #if COREFX
return type.GetTypeInfo().IsGenericType; type.GetTypeInfo().IsGenericType;
#else #else
return type.IsGenericType; type.IsGenericType;
#endif #endif
}
public static bool IsInterface(this Type type) public static bool IsInterface(this Type type) =>
{
#if COREFX #if COREFX
return type.GetTypeInfo().IsInterface; type.GetTypeInfo().IsInterface;
#else #else
return type.IsInterface; type.IsInterface;
#endif #endif
}
#if COREFX #if COREFX
public static IEnumerable<Attribute> GetCustomAttributes(this Type type, bool inherit) public static IEnumerable<Attribute> GetCustomAttributes(this Type type, bool inherit)
{ {
...@@ -56,8 +50,7 @@ public static IEnumerable<Attribute> GetCustomAttributes(this Type type, bool in ...@@ -56,8 +50,7 @@ public static IEnumerable<Attribute> GetCustomAttributes(this Type type, bool in
public static TypeCode GetTypeCode(Type type) public static TypeCode GetTypeCode(Type type)
{ {
if (type == null) return TypeCode.Empty; if (type == null) return TypeCode.Empty;
TypeCode result; if (typeCodeLookup.TryGetValue(type, out TypeCode result)) return result;
if (typeCodeLookup.TryGetValue(type, out result)) return result;
if (type.IsEnum()) if (type.IsEnum())
{ {
...@@ -66,41 +59,38 @@ public static TypeCode GetTypeCode(Type type) ...@@ -66,41 +59,38 @@ public static TypeCode GetTypeCode(Type type)
} }
return TypeCode.Object; return TypeCode.Object;
} }
static readonly Dictionary<Type, TypeCode> typeCodeLookup = new Dictionary<Type, TypeCode>
private static readonly Dictionary<Type, TypeCode> typeCodeLookup = new Dictionary<Type, TypeCode>
{ {
{typeof(bool), TypeCode.Boolean }, [typeof(bool)] = TypeCode.Boolean,
{typeof(byte), TypeCode.Byte }, [typeof(byte)] = TypeCode.Byte,
{typeof(char), TypeCode.Char}, [typeof(char)] = TypeCode.Char,
{typeof(DateTime), TypeCode.DateTime}, [typeof(DateTime)] = TypeCode.DateTime,
{typeof(decimal), TypeCode.Decimal}, [typeof(decimal)] = TypeCode.Decimal,
{typeof(double), TypeCode.Double }, [typeof(double)] = TypeCode.Double,
{typeof(short), TypeCode.Int16 }, [typeof(short)] = TypeCode.Int16,
{typeof(int), TypeCode.Int32 }, [typeof(int)] = TypeCode.Int32,
{typeof(long), TypeCode.Int64 }, [typeof(long)] = TypeCode.Int64,
{typeof(object), TypeCode.Object}, [typeof(object)] = TypeCode.Object,
{typeof(sbyte), TypeCode.SByte }, [typeof(sbyte)] = TypeCode.SByte,
{typeof(float), TypeCode.Single }, [typeof(float)] = TypeCode.Single,
{typeof(string), TypeCode.String }, [typeof(string)] = TypeCode.String,
{typeof(ushort), TypeCode.UInt16 }, [typeof(ushort)] = TypeCode.UInt16,
{typeof(uint), TypeCode.UInt32 }, [typeof(uint)] = TypeCode.UInt32,
{typeof(ulong), TypeCode.UInt64 }, [typeof(ulong)] = TypeCode.UInt64,
}; };
#else #else
public static TypeCode GetTypeCode(Type type) public static TypeCode GetTypeCode(Type type) => Type.GetTypeCode(type);
{
return Type.GetTypeCode(type);
}
#endif #endif
public static MethodInfo GetPublicInstanceMethod(this Type type, string name, Type[] types) public static MethodInfo GetPublicInstanceMethod(this Type type, string name, Type[] types)
{ {
#if COREFX #if COREFX
var method = type.GetMethod(name, types); var method = type.GetMethod(name, types);
return (method != null && method.IsPublic && !method.IsStatic) ? method : null; return (method?.IsPublic == true && !method.IsStatic) ? method : null;
#else #else
return type.GetMethod(name, BindingFlags.Instance | BindingFlags.Public, null, types, null); return type.GetMethod(name, BindingFlags.Instance | BindingFlags.Public, null, types, null);
#endif #endif
} }
} }
} }
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
namespace Dapper namespace Dapper
{ {
partial class SqlMapper public static partial class SqlMapper
{ {
#if !COREFX #if !COREFX
/// <summary> /// <summary>
...@@ -21,6 +21,7 @@ public UdtTypeHandler(string udtTypeName) ...@@ -21,6 +21,7 @@ public UdtTypeHandler(string udtTypeName)
if (string.IsNullOrEmpty(udtTypeName)) throw new ArgumentException("Cannot be null or empty", udtTypeName); if (string.IsNullOrEmpty(udtTypeName)) throw new ArgumentException("Cannot be null or empty", udtTypeName);
this.udtTypeName = udtTypeName; this.udtTypeName = udtTypeName;
} }
object ITypeHandler.Parse(Type destinationType, object value) object ITypeHandler.Parse(Type destinationType, object value)
{ {
return value is DBNull ? null : value; return value is DBNull ? null : value;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
namespace Dapper namespace Dapper
{ {
internal class WrappedReader : IDataReader, IWrappedDataReader internal class WrappedReader : IWrappedDataReader
{ {
private IDataReader reader; private IDataReader reader;
private IDbCommand cmd; private IDbCommand cmd;
...@@ -17,6 +17,7 @@ public IDataReader Reader ...@@ -17,6 +17,7 @@ public IDataReader Reader
return tmp; return tmp;
} }
} }
IDbCommand IWrappedDataReader.Command IDbCommand IWrappedDataReader.Command
{ {
get get
...@@ -26,35 +27,24 @@ IDbCommand IWrappedDataReader.Command ...@@ -26,35 +27,24 @@ IDbCommand IWrappedDataReader.Command
return tmp; return tmp;
} }
} }
public WrappedReader(IDbCommand cmd, IDataReader reader) public WrappedReader(IDbCommand cmd, IDataReader reader)
{ {
this.cmd = cmd; this.cmd = cmd;
this.reader = reader; this.reader = reader;
} }
void IDataReader.Close() void IDataReader.Close() => reader?.Close();
{
reader?.Close();
}
int IDataReader.Depth => Reader.Depth; int IDataReader.Depth => Reader.Depth;
DataTable IDataReader.GetSchemaTable() DataTable IDataReader.GetSchemaTable() => Reader.GetSchemaTable();
{
return Reader.GetSchemaTable();
}
bool IDataReader.IsClosed => reader?.IsClosed ?? true; bool IDataReader.IsClosed => reader?.IsClosed ?? true;
bool IDataReader.NextResult() bool IDataReader.NextResult() => Reader.NextResult();
{
return Reader.NextResult();
}
bool IDataReader.Read() bool IDataReader.Read() => Reader.Read();
{
return Reader.Read();
}
int IDataReader.RecordsAffected => Reader.RecordsAffected; int IDataReader.RecordsAffected => Reader.RecordsAffected;
...@@ -69,115 +59,51 @@ void IDisposable.Dispose() ...@@ -69,115 +59,51 @@ void IDisposable.Dispose()
int IDataRecord.FieldCount => Reader.FieldCount; int IDataRecord.FieldCount => Reader.FieldCount;
bool IDataRecord.GetBoolean(int i) bool IDataRecord.GetBoolean(int i) => Reader.GetBoolean(i);
{
return Reader.GetBoolean(i);
}
byte IDataRecord.GetByte(int i) byte IDataRecord.GetByte(int i) => Reader.GetByte(i);
{
return Reader.GetByte(i);
}
long IDataRecord.GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length) long IDataRecord.GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length) =>
{ Reader.GetBytes(i, fieldOffset, buffer, bufferoffset, length);
return Reader.GetBytes(i, fieldOffset, buffer, bufferoffset, length);
}
char IDataRecord.GetChar(int i) char IDataRecord.GetChar(int i) => Reader.GetChar(i);
{
return Reader.GetChar(i);
}
long IDataRecord.GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length) long IDataRecord.GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length) =>
{ Reader.GetChars(i, fieldoffset, buffer, bufferoffset, length);
return Reader.GetChars(i, fieldoffset, buffer, bufferoffset, length);
}
IDataReader IDataRecord.GetData(int i) IDataReader IDataRecord.GetData(int i) => Reader.GetData(i);
{
return Reader.GetData(i);
}
string IDataRecord.GetDataTypeName(int i) string IDataRecord.GetDataTypeName(int i) => Reader.GetDataTypeName(i);
{
return Reader.GetDataTypeName(i);
}
DateTime IDataRecord.GetDateTime(int i) DateTime IDataRecord.GetDateTime(int i) => Reader.GetDateTime(i);
{
return Reader.GetDateTime(i);
}
decimal IDataRecord.GetDecimal(int i) decimal IDataRecord.GetDecimal(int i) => Reader.GetDecimal(i);
{
return Reader.GetDecimal(i);
}
double IDataRecord.GetDouble(int i) double IDataRecord.GetDouble(int i) => Reader.GetDouble(i);
{
return Reader.GetDouble(i);
}
Type IDataRecord.GetFieldType(int i) Type IDataRecord.GetFieldType(int i) => Reader.GetFieldType(i);
{
return Reader.GetFieldType(i);
}
float IDataRecord.GetFloat(int i) float IDataRecord.GetFloat(int i) => Reader.GetFloat(i);
{
return Reader.GetFloat(i);
}
Guid IDataRecord.GetGuid(int i) Guid IDataRecord.GetGuid(int i) => Reader.GetGuid(i);
{
return Reader.GetGuid(i);
}
short IDataRecord.GetInt16(int i) short IDataRecord.GetInt16(int i) => Reader.GetInt16(i);
{
return Reader.GetInt16(i);
}
int IDataRecord.GetInt32(int i) int IDataRecord.GetInt32(int i) => Reader.GetInt32(i);
{
return Reader.GetInt32(i);
}
long IDataRecord.GetInt64(int i) long IDataRecord.GetInt64(int i) => Reader.GetInt64(i);
{
return Reader.GetInt64(i);
}
string IDataRecord.GetName(int i) string IDataRecord.GetName(int i) => Reader.GetName(i);
{
return Reader.GetName(i);
}
int IDataRecord.GetOrdinal(string name) int IDataRecord.GetOrdinal(string name) => Reader.GetOrdinal(name);
{
return Reader.GetOrdinal(name);
}
string IDataRecord.GetString(int i) string IDataRecord.GetString(int i) => Reader.GetString(i);
{
return Reader.GetString(i);
}
object IDataRecord.GetValue(int i) object IDataRecord.GetValue(int i) => Reader.GetValue(i);
{
return Reader.GetValue(i);
}
int IDataRecord.GetValues(object[] values) int IDataRecord.GetValues(object[] values) => Reader.GetValues(values);
{
return Reader.GetValues(values);
}
bool IDataRecord.IsDBNull(int i) bool IDataRecord.IsDBNull(int i) => Reader.IsDBNull(i);
{
return Reader.IsDBNull(i);
}
object IDataRecord.this[string name] => Reader[name]; object IDataRecord.this[string name] => Reader[name];
......
...@@ -12,6 +12,7 @@ public override void SetValue(IDbDataParameter parameter, T value) ...@@ -12,6 +12,7 @@ public override void SetValue(IDbDataParameter parameter, T value)
parameter.DbType = DbType.Xml; parameter.DbType = DbType.Xml;
} }
} }
internal sealed class XmlDocumentHandler : XmlTypeHandler<XmlDocument> internal sealed class XmlDocumentHandler : XmlTypeHandler<XmlDocument>
{ {
protected override XmlDocument Parse(string xml) protected override XmlDocument Parse(string xml)
...@@ -20,13 +21,16 @@ protected override XmlDocument Parse(string xml) ...@@ -20,13 +21,16 @@ protected override XmlDocument Parse(string xml)
doc.LoadXml(xml); doc.LoadXml(xml);
return doc; return doc;
} }
protected override string Format(XmlDocument xml) => xml.OuterXml; protected override string Format(XmlDocument xml) => xml.OuterXml;
} }
internal sealed class XDocumentHandler : XmlTypeHandler<XDocument> internal sealed class XDocumentHandler : XmlTypeHandler<XDocument>
{ {
protected override XDocument Parse(string xml) => XDocument.Parse(xml); protected override XDocument Parse(string xml) => XDocument.Parse(xml);
protected override string Format(XDocument xml) => xml.ToString(); protected override string Format(XDocument xml) => xml.ToString();
} }
internal sealed class XElementHandler : XmlTypeHandler<XElement> internal sealed class XElementHandler : XmlTypeHandler<XElement>
{ {
protected override XElement Parse(string xml) => XElement.Parse(xml); protected override XElement Parse(string xml) => XElement.Parse(xml);
......
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