Commit 06abcbdf authored by mgravell's avatar mgravell

oops, fix crappy perf; also take out all @ code from parameters'

parent 0a28a98e
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
using System.Reflection.Emit; using System.Reflection.Emit;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Text.RegularExpressions;
namespace Dapper namespace Dapper
{ {
...@@ -27,7 +28,7 @@ public interface IDynamicParameters ...@@ -27,7 +28,7 @@ public interface IDynamicParameters
static Link<Type, Action<IDbCommand, bool>> bindByNameCache; static Link<Type, Action<IDbCommand, bool>> bindByNameCache;
static Action<IDbCommand, bool> GetBindByName(Type commandType) static Action<IDbCommand, bool> GetBindByName(Type commandType)
{ {
if(commandType == null) return null; // GIGO if (commandType == null) return null; // GIGO
Action<IDbCommand, bool> action; Action<IDbCommand, bool> action;
if (Link<Type, Action<IDbCommand, bool>>.TryGet(bindByNameCache, commandType, out action)) if (Link<Type, Action<IDbCommand, bool>>.TryGet(bindByNameCache, commandType, out action))
{ {
...@@ -66,7 +67,7 @@ public static bool TryGet(Link<TKey, TValue> link, TKey key, out TValue value) ...@@ -66,7 +67,7 @@ public static bool TryGet(Link<TKey, TValue> link, TKey key, out TValue value)
{ {
while (link != null) while (link != null)
{ {
if ((object)key==(object)link.Key) if ((object)key == (object)link.Key)
{ {
value = link.Value; value = link.Value;
return true; return true;
...@@ -222,6 +223,7 @@ private Identity(string sql, string connectionString, Type type, Type parameters ...@@ -222,6 +223,7 @@ private Identity(string sql, string connectionString, Type type, Type parameters
this.connectionString = connectionString; this.connectionString = connectionString;
this.type = type; this.type = type;
this.parametersType = parametersType; this.parametersType = parametersType;
this.gridIndex = gridIndex;
unchecked unchecked
{ {
hashCode = 17; // we *know* we are using this in a dictionary, so pre-compute this hashCode = 17; // we *know* we are using this in a dictionary, so pre-compute this
...@@ -272,7 +274,7 @@ public bool Equals(Identity other) ...@@ -272,7 +274,7 @@ public bool Equals(Identity other)
#if CSHARP30 #if CSHARP30
this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType
#else #else
this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null
#endif #endif
) )
{ {
...@@ -284,9 +286,9 @@ public bool Equals(Identity other) ...@@ -284,9 +286,9 @@ public bool Equals(Identity other)
var interfaces = multiExec.GetType().GetInterfaces(); var interfaces = multiExec.GetType().GetInterfaces();
var openType = typeof(IEnumerable<>); var openType = typeof(IEnumerable<>);
Type foundType = null; Type foundType = null;
for(int i = 0 ; i < interfaces.Length; i++) for (int i = 0; i < interfaces.Length; i++)
{ {
if(interfaces[i].IsGenericType && interfaces[i].GetGenericTypeDefinition() == openType) if (interfaces[i].IsGenericType && interfaces[i].GetGenericTypeDefinition() == openType)
{ // implementing more than one T is self-inflicted { // implementing more than one T is self-inflicted
foundType = interfaces[i].GetGenericArguments()[0]; foundType = interfaces[i].GetGenericArguments()[0];
identity = new Identity(sql, cnn, null, foundType, null); identity = new Identity(sql, cnn, null, foundType, null);
...@@ -335,9 +337,9 @@ public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, dyn ...@@ -335,9 +337,9 @@ public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, dyn
#if CSHARP30 #if CSHARP30
this IDbConnection cnn, string sql, object param, IDbTransaction transaction, bool buffered, int? commandTimeout, CommandType? commandType this IDbConnection cnn, string sql, object param, IDbTransaction transaction, bool buffered, int? commandTimeout, CommandType? commandType
#else #else
this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null
#endif #endif
) )
{ {
var data = QueryInternal<T>(cnn, sql, param as object, transaction, commandTimeout, commandType); var data = QueryInternal<T>(cnn, sql, param as object, transaction, commandTimeout, commandType);
return buffered ? data.ToList() : data; return buffered ? data.ToList() : data;
...@@ -350,10 +352,10 @@ public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, dyn ...@@ -350,10 +352,10 @@ public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, dyn
#if CSHARP30 #if CSHARP30
this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType this IDbConnection cnn, string sql, object param, IDbTransaction transaction, int? commandTimeout, CommandType? commandType
#else #else
this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null
#endif #endif
) )
{ {
Identity identity = new Identity(sql, cnn, typeof(GridReader), (object)param == null ? null : ((object)param).GetType(), null); Identity identity = new Identity(sql, cnn, typeof(GridReader), (object)param == null ? null : ((object)param).GetType(), null);
CacheInfo info = GetCacheInfo(identity); CacheInfo info = GetCacheInfo(identity);
...@@ -405,7 +407,6 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq ...@@ -405,7 +407,6 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq
} }
} }
} }
clean = false;
} }
finally finally
{ // throw away query plan on failure - could { // throw away query plan on failure - could
...@@ -434,9 +435,9 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq ...@@ -434,9 +435,9 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq
#if CSHARP30 #if CSHARP30
this IDbConnection cnn, string sql, Func<TFirst, TSecond, TReturn> map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType this IDbConnection cnn, string sql, Func<TFirst, TSecond, TReturn> map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType
#else #else
this IDbConnection cnn, string sql, Func<TFirst, TSecond, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null this IDbConnection cnn, string sql, Func<TFirst, TSecond, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null
#endif #endif
) )
{ {
return MultiMap<TFirst, TSecond, DontMap, DontMap, DontMap, TReturn>(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType); return MultiMap<TFirst, TSecond, DontMap, DontMap, DontMap, TReturn>(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType);
} }
...@@ -445,9 +446,9 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq ...@@ -445,9 +446,9 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq
#if CSHARP30 #if CSHARP30
this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TReturn> map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TReturn> map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType
#else #else
this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null
#endif #endif
) )
{ {
return MultiMap<TFirst, TSecond, TThird, DontMap, DontMap, TReturn>(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType); return MultiMap<TFirst, TSecond, TThird, DontMap, DontMap, TReturn>(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType);
} }
...@@ -456,9 +457,9 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq ...@@ -456,9 +457,9 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq
#if CSHARP30 #if CSHARP30
this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TFourth, TReturn> map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TFourth, TReturn> map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType
#else #else
this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TFourth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TFourth, TReturn> map, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null
#endif #endif
) )
{ {
return MultiMap<TFirst, TSecond, TThird, TFourth, DontMap, TReturn>(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType); return MultiMap<TFirst, TSecond, TThird, TFourth, DontMap, TReturn>(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType);
} }
...@@ -468,7 +469,7 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq ...@@ -468,7 +469,7 @@ private static IEnumerable<T> QueryInternal<T>(this IDbConnection cnn, string sq
return MultiMap<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType); return MultiMap<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(cnn, sql, map, param as object, transaction, buffered, splitOn, commandTimeout, commandType);
} }
#endif #endif
class DontMap {} class DontMap { }
static IEnumerable<TReturn> MultiMap<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>( static IEnumerable<TReturn> MultiMap<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>(
this IDbConnection cnn, string sql, object map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType) this IDbConnection cnn, string sql, object map, object param, IDbTransaction transaction, bool buffered, string splitOn, int? commandTimeout, CommandType? commandType)
{ {
...@@ -503,7 +504,7 @@ class DontMap {} ...@@ -503,7 +504,7 @@ class DontMap {}
for (pos = current + 1; pos < reader.FieldCount; pos++) for (pos = current + 1; pos < reader.FieldCount; pos++)
{ {
// some people like ID some id ... assuming case insensitive splits for now // some people like ID some id ... assuming case insensitive splits for now
if (splitOn=="*" || string.Equals(reader.GetName(pos), currentSplit, StringComparison.InvariantCultureIgnoreCase)) if (splitOn == "*" || string.Equals(reader.GetName(pos), currentSplit, StringComparison.InvariantCultureIgnoreCase))
{ {
break; break;
} }
...@@ -554,7 +555,7 @@ class DontMap {} ...@@ -554,7 +555,7 @@ class DontMap {}
if (info.OtherDeserializers.Length == 1) if (info.OtherDeserializers.Length == 1)
{ {
mapIt = r => ((Func<TFirst, TSecond,TReturn>)map)(deserializer(r), deserializer2(r)); mapIt = r => ((Func<TFirst, TSecond, TReturn>)map)(deserializer(r), deserializer2(r));
} }
if (info.OtherDeserializers.Length > 1) if (info.OtherDeserializers.Length > 1)
...@@ -570,7 +571,7 @@ class DontMap {} ...@@ -570,7 +571,7 @@ class DontMap {}
var deserializer4 = (Func<IDataReader, TFourth>)info.OtherDeserializers[2]; var deserializer4 = (Func<IDataReader, TFourth>)info.OtherDeserializers[2];
if (info.OtherDeserializers.Length == 3) if (info.OtherDeserializers.Length == 3)
{ {
mapIt = r => ((Func<TFirst, TSecond, TThird, TFourth, TReturn>)map)(deserializer(r), deserializer2(r), deserializer3(r),deserializer4(r)); mapIt = r => ((Func<TFirst, TSecond, TThird, TFourth, TReturn>)map)(deserializer(r), deserializer2(r), deserializer3(r), deserializer4(r));
} }
if (info.OtherDeserializers.Length > 3) if (info.OtherDeserializers.Length > 3)
...@@ -579,7 +580,7 @@ class DontMap {} ...@@ -579,7 +580,7 @@ class DontMap {}
throw new NotSupportedException(); throw new NotSupportedException();
#else #else
var deserializer5 = (Func<IDataReader, TFifth>)info.OtherDeserializers[3]; var deserializer5 = (Func<IDataReader, TFifth>)info.OtherDeserializers[3];
mapIt = r => ((Func<TFirst, TSecond, TThird, TFourth,TFifth,TReturn>)map)(deserializer(r), deserializer2(r), deserializer3(r), deserializer4(r),deserializer5(r)); mapIt = r => ((Func<TFirst, TSecond, TThird, TFourth, TFifth, TReturn>)map)(deserializer(r), deserializer2(r), deserializer3(r), deserializer4(r), deserializer5(r));
#endif #endif
} }
} }
...@@ -633,13 +634,13 @@ private static CacheInfo GetCacheInfo(Identity identity) ...@@ -633,13 +634,13 @@ private static CacheInfo GetCacheInfo(Identity identity)
{ {
#if !CSHARP30 #if !CSHARP30
// dynamic is passed in as Object ... by c# design // dynamic is passed in as Object ... by c# design
if (typeof (T) == typeof (object) if (typeof(T) == typeof(object)
|| typeof (T) == typeof (FastExpando)) || typeof(T) == typeof(FastExpando))
{ {
return GetDynamicDeserializer<T>(reader, startBound, length, returnNullIfFirstMissing); return GetDynamicDeserializer<T>(reader, startBound, length, returnNullIfFirstMissing);
} }
#endif #endif
if (typeof (T).IsClass && typeof (T) != typeof (string)) if (typeof(T).IsClass && typeof(T) != typeof(string))
{ {
return GetClassDeserializer<T>(reader, startBound, length, returnNullIfFirstMissing); return GetClassDeserializer<T>(reader, startBound, length, returnNullIfFirstMissing);
} }
...@@ -653,7 +654,7 @@ private class FastExpando : System.Dynamic.DynamicObject, IDictionary<string, ob ...@@ -653,7 +654,7 @@ private class FastExpando : System.Dynamic.DynamicObject, IDictionary<string, ob
public static FastExpando Attach(IDictionary<string, object> data) public static FastExpando Attach(IDictionary<string, object> data)
{ {
return new FastExpando {data = data}; return new FastExpando { data = data };
} }
public override bool TrySetMember(System.Dynamic.SetMemberBinder binder, object value) public override bool TrySetMember(System.Dynamic.SetMemberBinder binder, object value)
...@@ -782,7 +783,7 @@ IEnumerator IEnumerable.GetEnumerator() ...@@ -782,7 +783,7 @@ IEnumerator IEnumerable.GetEnumerator()
return return
r => r =>
{ {
IDictionary<string, object> row = new Dictionary<string,object>(length); IDictionary<string, object> row = new Dictionary<string, object>(length);
for (var i = startBound; i < startBound + length; i++) for (var i = startBound; i < startBound + length; i++)
{ {
var tmp = r.GetValue(i); var tmp = r.GetValue(i);
...@@ -830,17 +831,20 @@ public static void PackListParameters(IDbCommand command, string namePrefix, obj ...@@ -830,17 +831,20 @@ public static void PackListParameters(IDbCommand command, string namePrefix, obj
if (count == 0) if (count == 0)
{ {
command.CommandText = command.CommandText.Replace(namePrefix, "(SELECT NULL WHERE 1 = 0)"); command.CommandText = Regex.Replace(command.CommandText, @"[?@:]" + Regex.Escape(namePrefix), "(SELECT NULL WHERE 1 = 0)");
} }
else else
{ {
var sb = new StringBuilder("(").Append(namePrefix).Append(1); command.CommandText = Regex.Replace(command.CommandText, @"[?@:]" + Regex.Escape(namePrefix), match =>
{
var grp = match.Value;
var sb = new StringBuilder("(").Append(grp).Append(1);
for (int i = 2; i <= count; i++) for (int i = 2; i <= count; i++)
{ {
sb.Append(',').Append(namePrefix).Append(i); sb.Append(',').Append(grp).Append(i);
} }
string inQuery = sb.Append(')').ToString(); return sb.Append(')').ToString();
command.CommandText = command.CommandText.Replace(namePrefix, inQuery); });
} }
} }
...@@ -865,12 +869,12 @@ public static void PackListParameters(IDbCommand command, string namePrefix, obj ...@@ -865,12 +869,12 @@ public static void PackListParameters(IDbCommand command, string namePrefix, obj
foreach (var prop in type.GetProperties().OrderBy(p => p.Name)) foreach (var prop in type.GetProperties().OrderBy(p => p.Name))
{ {
if(prop.PropertyType == typeof(DbString)) if (prop.PropertyType == typeof(DbString))
{ {
il.Emit(OpCodes.Ldloc_0); // stack is now [parameters] [typed-param] il.Emit(OpCodes.Ldloc_0); // stack is now [parameters] [typed-param]
il.Emit(OpCodes.Callvirt, prop.GetGetMethod()); // stack is [parameters] [dbstring] il.Emit(OpCodes.Callvirt, prop.GetGetMethod()); // stack is [parameters] [dbstring]
il.Emit(OpCodes.Ldarg_0); // stack is now [parameters] [dbstring] [command] il.Emit(OpCodes.Ldarg_0); // stack is now [parameters] [dbstring] [command]
il.Emit(OpCodes.Ldstr, "@" + prop.Name); // stack is now [parameters] [dbstring] [command] [name] il.Emit(OpCodes.Ldstr, prop.Name); // stack is now [parameters] [dbstring] [command] [name]
il.EmitCall(OpCodes.Callvirt, typeof(DbString).GetMethod("AddParameter"), null); // stack is now [parameters] il.EmitCall(OpCodes.Callvirt, typeof(DbString).GetMethod("AddParameter"), null); // stack is now [parameters]
continue; continue;
} }
...@@ -879,7 +883,7 @@ public static void PackListParameters(IDbCommand command, string namePrefix, obj ...@@ -879,7 +883,7 @@ public static void PackListParameters(IDbCommand command, string namePrefix, obj
{ {
// this actually represents special handling for list types; // this actually represents special handling for list types;
il.Emit(OpCodes.Ldarg_0); // stack is now [parameters] [command] il.Emit(OpCodes.Ldarg_0); // stack is now [parameters] [command]
il.Emit(OpCodes.Ldstr, "@" + prop.Name); // stack is now [parameters] [command] [name] il.Emit(OpCodes.Ldstr, prop.Name); // stack is now [parameters] [command] [name]
il.Emit(OpCodes.Ldloc_0); // stack is now [parameters] [command] [name] [typed-param] il.Emit(OpCodes.Ldloc_0); // stack is now [parameters] [command] [name] [typed-param]
il.Emit(OpCodes.Callvirt, prop.GetGetMethod()); // stack is [parameters] [command] [name] [typed-value] il.Emit(OpCodes.Callvirt, prop.GetGetMethod()); // stack is [parameters] [command] [name] [typed-value]
if (prop.PropertyType.IsValueType) if (prop.PropertyType.IsValueType)
...@@ -895,7 +899,7 @@ public static void PackListParameters(IDbCommand command, string namePrefix, obj ...@@ -895,7 +899,7 @@ public static void PackListParameters(IDbCommand command, string namePrefix, obj
il.EmitCall(OpCodes.Callvirt, typeof(IDbCommand).GetMethod("CreateParameter"), null);// stack is now [parameters] [parameters] [parameter] il.EmitCall(OpCodes.Callvirt, typeof(IDbCommand).GetMethod("CreateParameter"), null);// stack is now [parameters] [parameters] [parameter]
il.Emit(OpCodes.Dup);// stack is now [parameters] [parameters] [parameter] [parameter] il.Emit(OpCodes.Dup);// stack is now [parameters] [parameters] [parameter] [parameter]
il.Emit(OpCodes.Ldstr, "@" + prop.Name); // stack is now [parameters] [parameters] [parameter] [parameter] [name] il.Emit(OpCodes.Ldstr, prop.Name); // stack is now [parameters] [parameters] [parameter] [parameter] [name]
il.EmitCall(OpCodes.Callvirt, typeof(IDataParameter).GetProperty("ParameterName").GetSetMethod(), null);// stack is now [parameters] [parameters] [parameter] il.EmitCall(OpCodes.Callvirt, typeof(IDataParameter).GetProperty("ParameterName").GetSetMethod(), null);// stack is now [parameters] [parameters] [parameter]
il.Emit(OpCodes.Dup);// stack is now [parameters] [parameters] [parameter] [parameter] il.Emit(OpCodes.Dup);// stack is now [parameters] [parameters] [parameter] [parameter]
...@@ -1033,9 +1037,9 @@ static readonly MethodInfo ...@@ -1033,9 +1037,9 @@ static readonly MethodInfo
#if CSHARP30 #if CSHARP30
IDataReader reader, int startBound, int length, bool returnNullIfFirstMissing IDataReader reader, int startBound, int length, bool returnNullIfFirstMissing
#else #else
IDataReader reader, int startBound = 0, int length = -1, bool returnNullIfFirstMissing = false IDataReader reader, int startBound = 0, int length = -1, bool returnNullIfFirstMissing = false
#endif #endif
) )
{ {
var dm = new DynamicMethod(string.Format("Deserialize{0}", Guid.NewGuid()), typeof(T), new[] { typeof(IDataReader) }, true); var dm = new DynamicMethod(string.Format("Deserialize{0}", Guid.NewGuid()), typeof(T), new[] { typeof(IDataReader) }, true);
...@@ -1082,7 +1086,7 @@ static readonly MethodInfo ...@@ -1082,7 +1086,7 @@ static readonly MethodInfo
// stack is empty // stack is empty
il.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes)); // stack is now [target] il.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes)); // stack is now [target]
bool first = true; bool first = true;
var @allDone = il.DefineLabel(); var allDone = il.DefineLabel();
foreach (var item in setters) foreach (var item in setters)
{ {
if (item.Property != null || item.Field != null) if (item.Property != null || item.Field != null)
...@@ -1175,7 +1179,7 @@ static readonly MethodInfo ...@@ -1175,7 +1179,7 @@ static readonly MethodInfo
il.Emit(OpCodes.Pop); il.Emit(OpCodes.Pop);
il.Emit(OpCodes.Ldnull); // stack is now [null] il.Emit(OpCodes.Ldnull); // stack is now [null]
il.Emit(OpCodes.Stloc_1); il.Emit(OpCodes.Stloc_1);
il.Emit(OpCodes.Br, @allDone); il.Emit(OpCodes.Br, allDone);
} }
il.MarkLabel(finishLabel); il.MarkLabel(finishLabel);
...@@ -1184,7 +1188,7 @@ static readonly MethodInfo ...@@ -1184,7 +1188,7 @@ static readonly MethodInfo
index += 1; index += 1;
} }
il.Emit(OpCodes.Stloc_1); // stack is empty il.Emit(OpCodes.Stloc_1); // stack is empty
il.MarkLabel(@allDone); il.MarkLabel(allDone);
il.BeginCatchBlock(typeof(Exception)); // stack is Exception il.BeginCatchBlock(typeof(Exception)); // stack is Exception
il.Emit(OpCodes.Ldloc_0); // stack is Exception, index il.Emit(OpCodes.Ldloc_0); // stack is Exception, index
il.Emit(OpCodes.Ldarg_0); // stack is Exception, index, reader il.Emit(OpCodes.Ldarg_0); // stack is Exception, index, reader
...@@ -1214,7 +1218,7 @@ public static void ThrowDataException(Exception ex, int index, IDataReader reade ...@@ -1214,7 +1218,7 @@ public static void ThrowDataException(Exception ex, int index, IDataReader reade
value = Convert.ToString(val) + " - " + Type.GetTypeCode(val.GetType()); value = Convert.ToString(val) + " - " + Type.GetTypeCode(val.GetType());
} }
} }
throw new DataException(string.Format("Error parsing column {0} ({1}={2})", index, name,value), ex); throw new DataException(string.Format("Error parsing column {0} ({1}={2})", index, name, value), ex);
} }
private static void EmitInt32(ILGenerator il, int value) private static void EmitInt32(ILGenerator il, int value)
{ {
...@@ -1333,7 +1337,7 @@ public void Dispose() ...@@ -1333,7 +1337,7 @@ public void Dispose()
} }
public class DynamicParameters : SqlMapper.IDynamicParameters public class DynamicParameters : SqlMapper.IDynamicParameters
{ {
Dictionary<string, ParamInfo> parameters = new Dictionary<string,ParamInfo>(); Dictionary<string, ParamInfo> parameters = new Dictionary<string, ParamInfo>();
class ParamInfo class ParamInfo
{ {
...@@ -1356,11 +1360,11 @@ public DynamicParameters(object template) ...@@ -1356,11 +1360,11 @@ public DynamicParameters(object template)
if (!prop.CanRead) continue; if (!prop.CanRead) continue;
var idx = prop.GetIndexParameters(); var idx = prop.GetIndexParameters();
if (idx != null && idx.Length != 0) continue; if (idx != null && idx.Length != 0) continue;
Add("@" + prop.Name, prop.GetValue(template, null), null, ParameterDirection.Input, null); Add(prop.Name, prop.GetValue(template, null), null, ParameterDirection.Input, null);
} }
foreach (FieldInfo field in template.GetType().GetFields(bindingFlags)) foreach (FieldInfo field in template.GetType().GetFields(bindingFlags))
{ {
Add("@" + field.Name, field.GetValue(template), null, ParameterDirection.Input, null); Add(field.Name, field.GetValue(template), null, ParameterDirection.Input, null);
} }
} }
...@@ -1371,13 +1375,27 @@ public DynamicParameters(object template) ...@@ -1371,13 +1375,27 @@ public DynamicParameters(object template)
#if CSHARP30 #if CSHARP30
string name, object value, DbType? dbType, ParameterDirection? direction, int? size string name, object value, DbType? dbType, ParameterDirection? direction, int? size
#else #else
string name, object value = null, DbType? dbType = null, ParameterDirection? direction = null, int? size = null string name, object value = null, DbType? dbType = null, ParameterDirection? direction = null, int? size = null
#endif #endif
) )
{ {
parameters[name] = new ParamInfo() { Name = name, Value = value, ParameterDirection = direction ?? ParameterDirection.Input, DbType = dbType, Size = size }; parameters[Clean(name)] = new ParamInfo() { Name = name, Value = value, ParameterDirection = direction ?? ParameterDirection.Input, DbType = dbType, Size = size };
} }
static string Clean(string name)
{
if (!string.IsNullOrEmpty(name))
{
switch (name[0])
{
case '@':
case ':':
case '?':
return name.Substring(1);
}
}
return name;
}
void SqlMapper.IDynamicParameters.AddParameters(IDbCommand command) void SqlMapper.IDynamicParameters.AddParameters(IDbCommand command)
{ {
...@@ -1411,7 +1429,7 @@ void SqlMapper.IDynamicParameters.AddParameters(IDbCommand command) ...@@ -1411,7 +1429,7 @@ void SqlMapper.IDynamicParameters.AddParameters(IDbCommand command)
public T Get<T>(string name) public T Get<T>(string name)
{ {
return (T)parameters[name].AttachedParam.Value; return (T)parameters[Clean(name)].AttachedParam.Value;
} }
} }
public sealed class DbString public sealed class DbString
......
...@@ -72,11 +72,17 @@ public void PassInIntArray() ...@@ -72,11 +72,17 @@ public void PassInIntArray()
.IsSequenceEqualTo(new[] { 1, 2, 3 }); .IsSequenceEqualTo(new[] { 1, 2, 3 });
} }
public void PassInEmptyIntArray()
{
connection.Query<int>("select * from (select 1 as Id union all select 2 union all select 3) as X where Id in @Ids", new { Ids = new int[0] })
.IsSequenceEqualTo(new int[0]);
}
public void TestReadMultipleIntegersWithSplitOnAny() public void TestReadMultipleIntegersWithSplitOnAny()
{ {
connection.Query<int,int,int,Tuple<int,int,int>>( connection.Query<int, int, int, Tuple<int, int, int>>(
"select 1,2,3 union all select 4,5,6", Tuple.Create, splitOn: "*") "select 1,2,3 union all select 4,5,6", Tuple.Create, splitOn: "*")
.IsSequenceEqualTo(new[] {Tuple.Create(1,2,3), Tuple.Create(4,5,6)}); .IsSequenceEqualTo(new[] { Tuple.Create(1, 2, 3), Tuple.Create(4, 5, 6) });
} }
public void TestDoubleParam() public void TestDoubleParam()
...@@ -131,7 +137,7 @@ public class Dog ...@@ -131,7 +137,7 @@ public class Dog
public void TestExtraFields() public void TestExtraFields()
{ {
var guid = Guid.NewGuid(); var guid = Guid.NewGuid();
var dog = connection.Query<Dog>("select '' as Extra, 1 as Age, 0.1 as Name1 , Id = @id", new { Id = guid}); var dog = connection.Query<Dog>("select '' as Extra, 1 as Age, 0.1 as Name1 , Id = @id", new { Id = guid });
dog.Count() dog.Count()
.IsEqualTo(1); .IsEqualTo(1);
...@@ -183,8 +189,8 @@ public void TestExpando() ...@@ -183,8 +189,8 @@ public void TestExpando()
public void TestStringList() public void TestStringList()
{ {
connection.Query<string>("select * from (select 'a' as x union all select 'b' union all select 'c') as T where x in @strings", new {strings = new[] {"a","b","c"}}) connection.Query<string>("select * from (select 'a' as x union all select 'b' union all select 'c') as T where x in @strings", new { strings = new[] { "a", "b", "c" } })
.IsSequenceEqualTo(new[] {"a","b","c"}); .IsSequenceEqualTo(new[] { "a", "b", "c" });
connection.Query<string>("select * from (select 'a' as x union all select 'b' union all select 'c') as T where x in @strings", new { strings = new string[0] }) connection.Query<string>("select * from (select 'a' as x union all select 'b' union all select 'c') as T where x in @strings", new { strings = new string[0] })
.IsSequenceEqualTo(new string[0]); .IsSequenceEqualTo(new string[0]);
...@@ -199,12 +205,12 @@ public void TestExecuteCommand() ...@@ -199,12 +205,12 @@ public void TestExecuteCommand()
insert #t insert #t
select @a a union all select @b select @a a union all select @b
set nocount on set nocount on
drop table #t", new {a=1, b=2 }).IsEqualTo(2); drop table #t", new { a = 1, b = 2 }).IsEqualTo(2);
} }
public void TestExecuteCommandWithHybridParameters() public void TestExecuteCommandWithHybridParameters()
{ {
var p = new DynamicParameters(new { a = 1, b = 2 }); var p = new DynamicParameters(new { a = 1, b = 2 });
p.Add("@c", dbType: DbType.Int32, direction: ParameterDirection.Output); p.Add("c", dbType: DbType.Int32, direction: ParameterDirection.Output);
connection.Execute(@"set @c = @a + @b", p); connection.Execute(@"set @c = @a + @b", p);
p.Get<int>("@c").IsEqualTo(3); p.Get<int>("@c").IsEqualTo(3);
} }
...@@ -591,21 +597,21 @@ public void TestEnumStrings() ...@@ -591,21 +597,21 @@ public void TestEnumStrings()
public void TestSupportForParamDictionary() public void TestSupportForParamDictionary()
{ {
var p = new DynamicParameters(); var p = new DynamicParameters();
p.Add("@name", "bob"); p.Add("name", "bob");
p.Add("@age", dbType: DbType.Int32, direction: ParameterDirection.Output); p.Add("age", dbType: DbType.Int32, direction: ParameterDirection.Output);
connection.Query<string>("set @age = 11 select @name", p).First().IsEqualTo("bob"); connection.Query<string>("set @age = 11 select @name", p).First().IsEqualTo("bob");
p.Get<int>("@age").IsEqualTo(11); p.Get<int>("age").IsEqualTo(11);
} }
public void TestProcSupport() public void TestProcSupport()
{ {
var p = new DynamicParameters(); var p = new DynamicParameters();
p.Add("@a", 11); p.Add("a", 11);
p.Add("@b", dbType: DbType.Int32, direction: ParameterDirection.Output); p.Add("b", dbType: DbType.Int32, direction: ParameterDirection.Output);
p.Add("@c", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue); p.Add("c", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);
connection.Execute(@"create proc #TestProc connection.Execute(@"create proc #TestProc
@a int, @a int,
...@@ -618,8 +624,8 @@ select 1111 ...@@ -618,8 +624,8 @@ select 1111
end"); end");
connection.Query<int>("#TestProc", p, commandType: CommandType.StoredProcedure).First().IsEqualTo(1111); connection.Query<int>("#TestProc", p, commandType: CommandType.StoredProcedure).First().IsEqualTo(1111);
p.Get<int>("@c").IsEqualTo(11); p.Get<int>("c").IsEqualTo(11);
p.Get<int>("@b").IsEqualTo(999); p.Get<int>("b").IsEqualTo(999);
} }
...@@ -670,8 +676,8 @@ public void TestFlexibleMultiMapping() ...@@ -670,8 +676,8 @@ public void TestFlexibleMultiMapping()
2 as AddressId, 'abc street' as Name, 1 as PersonId, 2 as AddressId, 'abc street' as Name, 1 as PersonId,
3 as Id, 'fred' as Name 3 as Id, 'fred' as Name
"; ";
var personWithAddress = connection.Query<Person, Address, Extra, Tuple<Person, Address,Extra>> var personWithAddress = connection.Query<Person, Address, Extra, Tuple<Person, Address, Extra>>
(sql, (p,a,e) => Tuple.Create(p, a, e), splitOn: "AddressId,Id").First(); (sql, (p, a, e) => Tuple.Create(p, a, e), splitOn: "AddressId,Id").First();
personWithAddress.Item1.PersonId.IsEqualTo(1); personWithAddress.Item1.PersonId.IsEqualTo(1);
personWithAddress.Item1.Name.IsEqualTo("bob"); personWithAddress.Item1.Name.IsEqualTo("bob");
...@@ -736,7 +742,7 @@ public void AddParameters(IDbCommand command) ...@@ -736,7 +742,7 @@ public void AddParameters(IDbCommand command)
} }
// Add the table parameter. // Add the table parameter.
var p = sqlCommand.Parameters.Add("@ints", SqlDbType.Structured); var p = sqlCommand.Parameters.Add("ints", SqlDbType.Structured);
p.Direction = ParameterDirection.Input; p.Direction = ParameterDirection.Input;
p.TypeName = "int_list_type"; p.TypeName = "int_list_type";
p.Value = number_list; p.Value = number_list;
...@@ -796,7 +802,7 @@ public void ParentChildIdentityAssociations() ...@@ -796,7 +802,7 @@ public void ParentChildIdentityAssociations()
return found; return found;
}).Distinct().ToDictionary(p => p.Id); }).Distinct().ToDictionary(p => p.Id);
parents.Count().IsEqualTo(3); parents.Count().IsEqualTo(3);
parents[1].Children.Select(c => c.Id).SequenceEqual(new[] { 1,2,4}).IsTrue(); parents[1].Children.Select(c => c.Id).SequenceEqual(new[] { 1, 2, 4 }).IsTrue();
parents[2].Children.Select(c => c.Id).SequenceEqual(new[] { 3 }).IsTrue(); parents[2].Children.Select(c => c.Id).SequenceEqual(new[] { 3 }).IsTrue();
parents[3].Children.Select(c => c.Id).SequenceEqual(new[] { 5 }).IsTrue(); parents[3].Children.Select(c => c.Id).SequenceEqual(new[] { 5 }).IsTrue();
} }
......
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