From f94e0d8a748fa2c504b52056b83552398786b2ec Mon Sep 17 00:00:00 2001 From: "simon.cropp" Date: Wed, 11 May 2011 20:59:56 +1000 Subject: [PATCH 1/7] use typeHandle --- Dapper/SqlMapper.cs | 74 ++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/Dapper/SqlMapper.cs b/Dapper/SqlMapper.cs index 02a6bf86..cceebf3c 100644 --- a/Dapper/SqlMapper.cs +++ b/Dapper/SqlMapper.cs @@ -26,51 +26,51 @@ namespace Dapper } static readonly ConcurrentDictionary queryCache = new ConcurrentDictionary(); - static readonly Dictionary typeMap; + static readonly Dictionary typeMap; static SqlMapper() { - typeMap = new Dictionary(); - typeMap[typeof(byte)] = DbType.Byte; - typeMap[typeof(sbyte)] = DbType.SByte; - typeMap[typeof(short)] = DbType.Int16; - typeMap[typeof(ushort)] = DbType.UInt16; - typeMap[typeof(int)] = DbType.Int32; - typeMap[typeof(uint)] = DbType.UInt32; - typeMap[typeof(long)] = DbType.Int64; - typeMap[typeof(ulong)] = DbType.UInt64; - typeMap[typeof(float)] = DbType.Single; - typeMap[typeof(double)] = DbType.Double; - typeMap[typeof(decimal)] = DbType.Decimal; - typeMap[typeof(bool)] = DbType.Boolean; - typeMap[typeof(string)] = DbType.String; - typeMap[typeof(char)] = DbType.StringFixedLength; - typeMap[typeof(Guid)] = DbType.Guid; - typeMap[typeof(DateTime)] = DbType.DateTime; - typeMap[typeof(DateTimeOffset)] = DbType.DateTimeOffset; - typeMap[typeof(byte[])] = DbType.Binary; - typeMap[typeof(byte?)] = DbType.Byte; - typeMap[typeof(sbyte?)] = DbType.SByte; - typeMap[typeof(short?)] = DbType.Int16; - typeMap[typeof(ushort?)] = DbType.UInt16; - typeMap[typeof(int?)] = DbType.Int32; - typeMap[typeof(uint?)] = DbType.UInt32; - typeMap[typeof(long?)] = DbType.Int64; - typeMap[typeof(ulong?)] = DbType.UInt64; - typeMap[typeof(float?)] = DbType.Single; - typeMap[typeof(double?)] = DbType.Double; - typeMap[typeof(decimal?)] = DbType.Decimal; - typeMap[typeof(bool?)] = DbType.Boolean; - typeMap[typeof(char?)] = DbType.StringFixedLength; - typeMap[typeof(Guid?)] = DbType.Guid; - typeMap[typeof(DateTime?)] = DbType.DateTime; - typeMap[typeof(DateTimeOffset?)] = DbType.DateTimeOffset; + typeMap = new Dictionary(); + typeMap[typeof(byte).TypeHandle] = DbType.Byte; + typeMap[typeof(sbyte).TypeHandle] = DbType.SByte; + typeMap[typeof(short).TypeHandle] = DbType.Int16; + typeMap[typeof(ushort).TypeHandle] = DbType.UInt16; + typeMap[typeof(int).TypeHandle] = DbType.Int32; + typeMap[typeof(uint).TypeHandle] = DbType.UInt32; + typeMap[typeof(long).TypeHandle] = DbType.Int64; + typeMap[typeof(ulong).TypeHandle] = DbType.UInt64; + typeMap[typeof(float).TypeHandle] = DbType.Single; + typeMap[typeof(double).TypeHandle] = DbType.Double; + typeMap[typeof(decimal).TypeHandle] = DbType.Decimal; + typeMap[typeof(bool).TypeHandle] = DbType.Boolean; + typeMap[typeof(string).TypeHandle] = DbType.String; + typeMap[typeof(char).TypeHandle] = DbType.StringFixedLength; + typeMap[typeof(Guid).TypeHandle] = DbType.Guid; + typeMap[typeof(DateTime).TypeHandle] = DbType.DateTime; + typeMap[typeof(DateTimeOffset).TypeHandle] = DbType.DateTimeOffset; + typeMap[typeof(byte[]).TypeHandle] = DbType.Binary; + typeMap[typeof(byte?).TypeHandle] = DbType.Byte; + typeMap[typeof(sbyte?).TypeHandle] = DbType.SByte; + typeMap[typeof(short?).TypeHandle] = DbType.Int16; + typeMap[typeof(ushort?).TypeHandle] = DbType.UInt16; + typeMap[typeof(int?).TypeHandle] = DbType.Int32; + typeMap[typeof(uint?).TypeHandle] = DbType.UInt32; + typeMap[typeof(long?).TypeHandle] = DbType.Int64; + typeMap[typeof(ulong?).TypeHandle] = DbType.UInt64; + typeMap[typeof(float?).TypeHandle] = DbType.Single; + typeMap[typeof(double?).TypeHandle] = DbType.Double; + typeMap[typeof(decimal?).TypeHandle] = DbType.Decimal; + typeMap[typeof(bool?).TypeHandle] = DbType.Boolean; + typeMap[typeof(char?).TypeHandle] = DbType.StringFixedLength; + typeMap[typeof(Guid?).TypeHandle] = DbType.Guid; + typeMap[typeof(DateTime?).TypeHandle] = DbType.DateTime; + typeMap[typeof(DateTimeOffset?).TypeHandle] = DbType.DateTimeOffset; } private static DbType LookupDbType(Type type) { DbType dbType; - if (typeMap.TryGetValue(type, out dbType)) + if (typeMap.TryGetValue(type.TypeHandle, out dbType)) { return dbType; } From c17a5454592517f388e8d2909731e3c1bb8994b9 Mon Sep 17 00:00:00 2001 From: "simon.cropp" Date: Wed, 11 May 2011 21:01:16 +1000 Subject: [PATCH 2/7] remove some unused properties --- Dapper/SqlMapper.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Dapper/SqlMapper.cs b/Dapper/SqlMapper.cs index cceebf3c..52a3ae9b 100644 --- a/Dapper/SqlMapper.cs +++ b/Dapper/SqlMapper.cs @@ -86,17 +86,12 @@ namespace Dapper private class Identity : IEquatable { - public String ConnectionString { get { return connectionString; } } - public Type Type { get { return type; } } - public string Sql { get { return sql; } } - public Type ParametersType { get { return ParametersType; } } internal Identity(string sql, IDbConnection cnn, Type type, Type parametersType, Type[] otherTypes = null) { this.sql = sql; this.connectionString = cnn.ConnectionString; this.type = type; this.parametersType = parametersType; - this.otherTypes = otherTypes; unchecked { hashCode = 17; // we *know* we are using this in a dictionary, so pre-compute this @@ -120,7 +115,6 @@ namespace Dapper private readonly string sql; private readonly int hashCode; private readonly Type type; - private readonly Type[] otherTypes; private readonly string connectionString; private readonly Type parametersType; public override int GetHashCode() From 8ecd21cf20de828e1cb423b1cd21b32c5fdc1646 Mon Sep 17 00:00:00 2001 From: "simon.cropp" Date: Wed, 11 May 2011 21:11:15 +1000 Subject: [PATCH 3/7] avoid some casting by more use of generics --- Dapper/SqlMapper.cs | 38 +++++++++++++------------------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/Dapper/SqlMapper.cs b/Dapper/SqlMapper.cs index 52a3ae9b..4f9c18d5 100644 --- a/Dapper/SqlMapper.cs +++ b/Dapper/SqlMapper.cs @@ -375,24 +375,17 @@ namespace Dapper private static Func GetDeserializer(Identity identity, IDataReader reader, int startBound = 0, int length = -1, bool returnNullIfFirstMissing = false) { - object oDeserializer; - // dynamic is passed in as Object ... by c# design - if (typeof(T) == typeof(object) || typeof(T) == typeof(FastExpando)) + if (typeof (T) == typeof (object) || typeof (T) == typeof (FastExpando)) { - oDeserializer = GetDynamicDeserializer(reader,startBound, length, returnNullIfFirstMissing); + return GetDynamicDeserializer(reader, startBound, length, returnNullIfFirstMissing); } - else if (typeof(T).IsClass && typeof(T) != typeof(string)) + if (typeof (T).IsClass && typeof (T) != typeof (string)) { - oDeserializer = GetClassDeserializer(reader, startBound, length, returnNullIfFirstMissing: returnNullIfFirstMissing); - } - else - { - oDeserializer = GetStructDeserializer(reader); + return GetClassDeserializer(reader, startBound, length, returnNullIfFirstMissing); } + return GetStructDeserializer(reader); - var deserializer = (Func)oDeserializer; - return deserializer; } private class FastExpando : DynamicObject @@ -401,9 +394,7 @@ namespace Dapper public static FastExpando Attach(IDictionary data) { - FastExpando expando = new FastExpando(); - expando.data = data; - return expando; + return new FastExpando {data = data}; } public override bool TrySetMember(SetMemberBinder binder, object value) @@ -418,14 +409,14 @@ namespace Dapper } } - private static object GetDynamicDeserializer(IDataRecord reader, int startBound = 0, int length = -1, bool returnNullIfFirstMissing = false) + private static Func GetDynamicDeserializer(IDataRecord reader, int startBound = 0, int length = -1, bool returnNullIfFirstMissing = false) { if (length == -1) { length = reader.FieldCount - startBound; } - Func rval = + return r => { IDictionary row = new Dictionary(length); @@ -436,13 +427,13 @@ namespace Dapper row[r.GetName(i)] = tmp; if (returnNullIfFirstMissing && i == startBound && tmp == null) { - return null; + return default(T); } } - return FastExpando.Attach(row); + //we know this is an object so it will not box + return (T)(object)FastExpando.Attach(row); }; - return rval; } [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] [Obsolete("This method is for internal usage only", true)] @@ -640,11 +631,9 @@ namespace Dapper } } - private static object GetStructDeserializer(IDataReader reader) + private static Func GetStructDeserializer(IDataReader reader) { - Func deserializer = null; - - deserializer = r => + return r => { var val = r.GetValue(0); if (val == DBNull.Value) @@ -653,7 +642,6 @@ namespace Dapper } return (T)val; }; - return deserializer; } public static Func GetClassDeserializer(IDataReader reader, int startBound = 0, int length = -1, bool returnNullIfFirstMissing = false) From 70fe2354f1c6190915f0618210e6ce00c0ec9d47 Mon Sep 17 00:00:00 2001 From: "simon.cropp" Date: Wed, 11 May 2011 21:15:47 +1000 Subject: [PATCH 4/7] remove some unused code --- Dapper/SqlMapper.cs | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/Dapper/SqlMapper.cs b/Dapper/SqlMapper.cs index 4f9c18d5..d3305495 100644 --- a/Dapper/SqlMapper.cs +++ b/Dapper/SqlMapper.cs @@ -197,7 +197,7 @@ namespace Dapper { if (info.Deserializer == null) { - info.Deserializer = GetDeserializer(identity, reader); + info.Deserializer = GetDeserializer(reader); queryCache[identity] = info; } @@ -284,30 +284,30 @@ namespace Dapper var otherDeserializer = new List(); split = nextSplit(); - info.Deserializer = GetDeserializer(identity, reader, 0, split); + info.Deserializer = GetDeserializer(reader, 0, split); if (typeof(TSecond) != typeof(DontMap)) { var next = nextSplit(); - otherDeserializer.Add(GetDeserializer(identity, reader, split, next - split, returnNullIfFirstMissing: true)); + otherDeserializer.Add(GetDeserializer(reader, split, next - split, returnNullIfFirstMissing: true)); split = next; } if (typeof(TThird) != typeof(DontMap)) { var next = nextSplit(); - otherDeserializer.Add(GetDeserializer(identity, reader, split, next - split, returnNullIfFirstMissing: true)); + otherDeserializer.Add(GetDeserializer(reader, split, next - split, returnNullIfFirstMissing: true)); split = next; } if (typeof(TFourth) != typeof(DontMap)) { var next = nextSplit(); - otherDeserializer.Add(GetDeserializer(identity, reader, split, next - split, returnNullIfFirstMissing: true)); + otherDeserializer.Add(GetDeserializer(reader, split, next - split, returnNullIfFirstMissing: true)); split = next; } if (typeof(TFifth) != typeof(DontMap)) { var next = nextSplit(); - otherDeserializer.Add(GetDeserializer(identity, reader, split, next - split, returnNullIfFirstMissing: true)); + otherDeserializer.Add(GetDeserializer(reader, split, next - split, returnNullIfFirstMissing: true)); } info.OtherDeserializers = otherDeserializer.ToArray(); @@ -373,7 +373,7 @@ namespace Dapper return info; } - private static Func GetDeserializer(Identity identity, IDataReader reader, int startBound = 0, int length = -1, bool returnNullIfFirstMissing = false) + private static Func GetDeserializer(IDataReader reader, int startBound = 0, int length = -1, bool returnNullIfFirstMissing = false) { // dynamic is passed in as Object ... by c# design if (typeof (T) == typeof (object) || typeof (T) == typeof (FastExpando)) @@ -384,7 +384,7 @@ namespace Dapper { return GetClassDeserializer(reader, startBound, length, returnNullIfFirstMissing); } - return GetStructDeserializer(reader); + return GetStructDeserializer(); } @@ -631,7 +631,7 @@ namespace Dapper } } - private static Func GetStructDeserializer(IDataReader reader) + private static Func GetStructDeserializer() { return r => { @@ -691,7 +691,7 @@ namespace Dapper int index = startBound; - var @try = il.BeginExceptionBlock(); + il.BeginExceptionBlock(); // stack is empty il.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes)); // stack is now [target] bool first = true; @@ -827,8 +827,7 @@ namespace Dapper { if (reader == null) throw new ObjectDisposedException(GetType().Name); if (consumed) throw new InvalidOperationException("Each grid can only be iterated once"); - var identity = new Identity(sql, connection, typeof(T), null); - var deserializer = SqlMapper.GetDeserializer(identity, reader); + var deserializer = GetDeserializer(reader); consumed = true; return ReadDeferred(gridIndex, deserializer); } From 5488e8c62abd09c155e8c99ccc4bceb9e4da9911 Mon Sep 17 00:00:00 2001 From: "simon.cropp" Date: Wed, 11 May 2011 21:17:15 +1000 Subject: [PATCH 5/7] move some variables closer to usage --- Dapper/SqlMapper.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Dapper/SqlMapper.cs b/Dapper/SqlMapper.cs index d3305495..0e23b4ba 100644 --- a/Dapper/SqlMapper.cs +++ b/Dapper/SqlMapper.cs @@ -263,7 +263,6 @@ namespace Dapper { if (info.Deserializer == null) { - var split = 0; int current = 0; Func nextSplit = () => @@ -283,7 +282,7 @@ namespace Dapper var otherDeserializer = new List(); - split = nextSplit(); + int split = nextSplit(); info.Deserializer = GetDeserializer(reader, 0, split); if (typeof(TSecond) != typeof(DontMap)) @@ -444,10 +443,10 @@ namespace Dapper var list = value as IEnumerable; var count = 0; - bool isString = value is IEnumerable; if (list != null) { + bool isString = value is IEnumerable; foreach (var item in list) { count++; From a8b4ae893932902a057c474c13ace8a83c7014b0 Mon Sep 17 00:00:00 2001 From: "simon.cropp" Date: Wed, 11 May 2011 21:25:58 +1000 Subject: [PATCH 6/7] no point null checking because these parameters will ahve been used already --- Dapper/SqlMapper.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Dapper/SqlMapper.cs b/Dapper/SqlMapper.cs index 0e23b4ba..59e756aa 100644 --- a/Dapper/SqlMapper.cs +++ b/Dapper/SqlMapper.cs @@ -8,6 +8,7 @@ using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Data; +using System.Diagnostics; using System.Dynamic; using System.Linq; using System.Reflection; @@ -809,11 +810,6 @@ namespace Dapper private readonly string sql; internal GridReader(IDbCommand command, IDataReader reader, IDbConnection connection, string sql) { - if (reader == null) throw new ArgumentNullException("reader"); - if (connection == null) throw new ArgumentNullException("connection"); - if (sql == null) throw new ArgumentNullException("sql"); - if (command == null) throw new ArgumentNullException("command"); - this.sql = sql; this.command = command; this.connection = connection; From 52614f5703ae3b0c4e0460b2610c44327365f609 Mon Sep 17 00:00:00 2001 From: "simon.cropp" Date: Wed, 11 May 2011 21:26:54 +1000 Subject: [PATCH 7/7] remove more unused code --- Dapper/SqlMapper.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/Dapper/SqlMapper.cs b/Dapper/SqlMapper.cs index 59e756aa..2505152a 100644 --- a/Dapper/SqlMapper.cs +++ b/Dapper/SqlMapper.cs @@ -174,7 +174,7 @@ namespace Dapper { cmd = SetupCommand(cnn, transaction, sql, info.ParamReader, param, commandTimeout); reader = cmd.ExecuteReader(); - return new GridReader(cmd, reader, cnn, sql); + return new GridReader(cmd, reader); } catch { @@ -805,14 +805,10 @@ namespace Dapper public class GridReader : IDisposable { private IDataReader reader; - private IDbConnection connection; private IDbCommand command; - private readonly string sql; - internal GridReader(IDbCommand command, IDataReader reader, IDbConnection connection, string sql) + internal GridReader(IDbCommand command, IDataReader reader) { - this.sql = sql; this.command = command; - this.connection = connection; this.reader = reader; } /// @@ -863,7 +859,6 @@ namespace Dapper } public void Dispose() { - connection = null; if (reader != null) { reader.Dispose();