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;
}
}
}
}