using System; using System.Collections.Generic; using System.Data; namespace Dapper { partial class SqlMapper { /// /// Parses a data reader to a sequence of data of the supplied type. Used for deserializing a reader without a connection, etc. /// public static IEnumerable Parse(this IDataReader reader) { if(reader.Read()) { var deser = GetDeserializer(typeof(T), reader, 0, -1, false); do { yield return (T)deser(reader); } while (reader.Read()); } } /// /// Parses a data reader to a sequence of data of the supplied type (as object). Used for deserializing a reader without a connection, etc. /// public static IEnumerable Parse(this IDataReader reader, Type type) { if (reader.Read()) { var deser = GetDeserializer(type, reader, 0, -1, false); do { yield return deser(reader); } while (reader.Read()); } } /// /// Parses a data reader to a sequence of dynamic. Used for deserializing a reader without a connection, etc. /// public static IEnumerable Parse(this IDataReader reader) { if (reader.Read()) { var deser = GetDapperRowDeserializer(reader, 0, -1, false); do { yield return deser(reader); } while (reader.Read()); } } /// /// 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. /// /// The data reader to get the parser for the current row from /// The type to get the parser for /// The start column index of the object (default 0) /// The length of columns to read (default -1 = all fields following startIndex) /// Return null if we can't find the first column? (default false) /// A parser for this specific object from this row. public static Func GetRowParser(this IDataReader reader, Type type, int startIndex = 0, int length = -1, bool returnNullIfFirstMissing = false) { return GetDeserializer(type, reader, startIndex, length, returnNullIfFirstMissing); } /// /// 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. /// /// The data reader to get the parser for the current row from /// The type to get the parser for /// The start column index of the object (default 0) /// The length of columns to read (default -1 = all fields following startIndex) /// Return null if we can't find the first column? (default false) /// A parser for this specific object from this row. /// /// var result = new List<BaseType>(); /// using (var reader = connection.ExecuteReader(@" /// select 'abc' as Name, 1 as Type, 3.0 as Value /// union all /// select 'def' as Name, 2 as Type, 4.0 as Value")) /// { /// if (reader.Read()) /// { /// var toFoo = reader.GetRowParser<BaseType>(typeof(Foo)); /// var toBar = reader.GetRowParser<BaseType>(typeof(Bar)); /// var col = reader.GetOrdinal("Type"); /// do /// { /// switch (reader.GetInt32(col)) /// { /// case 1: /// result.Add(toFoo(reader)); /// break; /// case 2: /// result.Add(toBar(reader)); /// break; /// } /// } while (reader.Read()); /// } /// } /// /// abstract class BaseType /// { /// public abstract int Type { get; } /// } /// class Foo : BaseType /// { /// public string Name { get; set; } /// public override int Type => 1; /// } /// class Bar : BaseType /// { /// public float Value { get; set; } /// public override int Type => 2; /// } /// public static Func GetRowParser(this IDataReader reader, Type concreteType = null, int startIndex = 0, int length = -1, bool returnNullIfFirstMissing = false) { if (concreteType == null) concreteType = typeof(T); var func = GetDeserializer(concreteType, reader, startIndex, length, returnNullIfFirstMissing); if (concreteType.IsValueType()) { return _ => (T)func(_); } else { return (Func)(Delegate)func; } } } }