From 4a364589629f608ba95d687b0d371a344b621ec1 Mon Sep 17 00:00:00 2001 From: Sam Saffron Date: Wed, 20 Apr 2011 13:31:43 +1000 Subject: [PATCH] added support for enumeration, so you can work through big lists if needed --- Dapper/SqlMapper.cs | 48 +++++++++++++++++++++++++++++++++++------- Tests/Tests.cs | 51 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 9 deletions(-) diff --git a/Dapper/SqlMapper.cs b/Dapper/SqlMapper.cs index edc5e26..30f9533 100644 --- a/Dapper/SqlMapper.cs +++ b/Dapper/SqlMapper.cs @@ -45,7 +45,6 @@ static SqlMapper() 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; @@ -62,7 +61,6 @@ static SqlMapper() typeMap[typeof(Guid?)] = DbType.Guid; typeMap[typeof(DateTime?)] = DbType.DateTime; typeMap[typeof(DateTimeOffset?)] = DbType.DateTimeOffset; - } private static DbType LookupDbType(Type type) @@ -84,7 +82,6 @@ private static DbType LookupDbType(Type type) throw new NotSupportedException("The type : " + type.ToString() + " is not supported by the mapper"); } - class ParamInfo { private ParamInfo() @@ -150,6 +147,43 @@ static class DynamicStub public static Type Type = typeof(DynamicStub); } + /// + /// Enumerates the query, keeping the reader open after it is called. Use when iterating through huge result sets . You should usually use ExecuteMapperQuery instead. + /// + public static IEnumerable EnumerateMapperQuery(this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null) + { + var identity = new Identity(sql, cnn, typeof(T)); + + using (var reader = GetReader(cnn, transaction, sql, GetParamInfo(param))) + { + Func deserializer = GetDeserializer(identity, reader); + while (reader.Read()) + { + yield return deserializer(reader); + } + } + } + + /// + /// Enumerates the query, keeping the reader open after it is called. Use when iterating through huge result sets. You should usually use ExecuteMapperQuery instead + /// + public static IEnumerable EnumerateMapperQuery(this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null) + { + var identity = new Identity(sql, cnn, DynamicStub.Type); + + using (var reader = GetReader(cnn, transaction, sql, GetParamInfo(param))) + { + Func deserializer = GetDeserializer(identity, reader); + while (reader.Read()) + { + yield return deserializer(reader); + } + } + } + + /// + /// Return a list of dynamic objects, reader is closed after the call + /// public static List ExecuteMapperQuery(this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null) { var identity = new Identity(sql, cnn, DynamicStub.Type); @@ -166,7 +200,9 @@ public static List ExecuteMapperQuery(this IDbConnection cnn, string sq return list; } - + /// + /// Return a typed list of objects, reader is closed after the call + /// public static List ExecuteMapperQuery(this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null) { var identity = new Identity(sql, cnn, typeof(T)); @@ -180,10 +216,7 @@ public static List ExecuteMapperQuery(this IDbConnection cnn, string sql, { rval.Add(deserializer(reader)); } - // ignore any other grids; note that this might mean we miss exceptions that happen - // late in the TDS stream, but that is bad design anyhow } - return rval; } @@ -480,6 +513,5 @@ private static void EmitInt32(ILGenerator il, int value) default: il.Emit(OpCodes.Ldc_I4, value); break; } } - } } diff --git a/Tests/Tests.cs b/Tests/Tests.cs index c22c45d..43d1ce6 100644 --- a/Tests/Tests.cs +++ b/Tests/Tests.cs @@ -34,6 +34,14 @@ public static void IsFalse(this bool b) } } + public static void IsTrue(this bool b) + { + if (b) + { + throw new ApplicationException("Expected true"); + } + } + public static void IsNull(this object obj) { if (obj != null) @@ -187,7 +195,48 @@ public void TestSetPrivate() connection.ExecuteMapperQuery("select 10 as [Priv]").First()._priv.IsEqualTo(10); } - + public void TestEnumeration() + { + var en = connection.EnumerateMapperQuery("select 1 as one"); + bool gotException = false; + try + { + connection.EnumerateMapperQuery("select 1 as one"); + } + catch (Exception) + { + gotException = true; + } + + var realItems = en.ToList(); + + // should not exception, since enumertated + en = connection.EnumerateMapperQuery("select 1 as one"); + + gotException.IsTrue(); + } + + public void TestEnumerationDynamic() + { + var en = connection.EnumerateMapperQuery("select 1 as one"); + bool gotException = false; + try + { + connection.EnumerateMapperQuery("select 1 as one"); + } + catch (Exception) + { + gotException = true; + } + + int i = en.First().one; + i.IsEqualTo(1); + + // should not exception, since enumertated + en = connection.EnumerateMapperQuery("select 1 as one"); + + gotException.IsTrue(); + } } } -- GitLab