diff --git a/Dapper/SqlMapper.cs b/Dapper/SqlMapper.cs index 47fc9b67e51d06433a3849e9fd388e19b8a5efe6..16d42ebd205366b1e4e7ea74d8173ec96602d125 100644 --- a/Dapper/SqlMapper.cs +++ b/Dapper/SqlMapper.cs @@ -195,13 +195,17 @@ private static IEnumerable QueryInternal(this IDbConnection cnn, string sq { using (var reader = cmd.ExecuteReader()) { + Func deserializer; if (info.Deserializer == null) { - info.Deserializer = GetDeserializer(identity, reader); + info.Deserializer = deserializer = GetDeserializer(reader); queryCache[identity] = info; } + else + { + deserializer = (Func)info.Deserializer; + } - var deserializer = (Func)info.Deserializer; while (reader.Read()) { @@ -283,30 +287,30 @@ class DontMap {} var otherDeserializer = new List(); int split = nextSplit(); - info.Deserializer = GetDeserializer(identity, reader, 0, split); + info.Deserializer = GetDeserializer(reader, 0, split); if (typeof(U) != 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(V) != 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(Z) != 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(X) != 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(); @@ -382,27 +386,33 @@ class DontMap {} private static CacheInfo GetCacheInfo(object param, Identity identity) { CacheInfo info; - if (!queryCache.TryGetValue(identity, out info)) + if (queryCache.TryGetValue(identity, out info)) { - info = new CacheInfo(); - if (param != null) - { - info.ParamReader = CreateParamInfoGenerator(param.GetType()); - } + return info; + } + info = new CacheInfo(); + if (param != null) + { + info.ParamReader = CreateParamInfoGenerator(param.GetType()); } return info; } - private static Func GetDeserializer(Identity identity, IDataReader reader, int startBound = 0, int length = -1, bool returnNullIfFirstMissing = false) + static RuntimeTypeHandle objectTypeHandle = typeof(object).TypeHandle; + static RuntimeTypeHandle expandoTypeHandle = typeof(ExpandoObject).TypeHandle; + static RuntimeTypeHandle stringTypeHandle = typeof(string).TypeHandle; + + 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(ExpandoObject)) + var tHandle = typeof(T).TypeHandle; + if (tHandle.Equals(objectTypeHandle) || tHandle.Equals(expandoTypeHandle)) { return GetDynamicDeserializer(reader,startBound, length, returnNullIfFirstMissing); } - if (typeof(T).IsClass && typeof(T) != typeof(string)) + if (typeof(T).IsClass && !tHandle.Equals(stringTypeHandle)) { - return GetClassDeserializer(reader, startBound, length, returnNullIfFirstMissing: returnNullIfFirstMissing); + return GetClassDeserializer(reader, startBound, length, returnNullIfFirstMissing); } return GetStructDeserializer(); @@ -784,8 +794,7 @@ public IEnumerable Read() { 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 = GetDeserializer(identity, reader); + var deserializer = GetDeserializer(reader); consumed = true; return ReadDeferred(gridIndex, deserializer); }