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