Skip to content

Instantly share code, notes, and snippets.

@darrenkopp
Last active March 26, 2025 03:02
Show Gist options
  • Save darrenkopp/5005932 to your computer and use it in GitHub Desktop.
Save darrenkopp/5005932 to your computer and use it in GitHub Desktop.

Revisions

  1. darrenkopp revised this gist Feb 21, 2013. 2 changed files with 201 additions and 197 deletions.
    257 changes: 130 additions & 127 deletions DataReaderExtensions.cs
    Original file line number Diff line number Diff line change
    @@ -1,143 +1,146 @@
    public static IEnumerable<T> Stream<T>(this IDbCommand command, Func<IDataRecord, T> converter)
    public static class DataReaderExtensions
    {
    public static IEnumerable<T> Stream<T>(this IDbCommand command, Func<IDataRecord, T> converter)
    {
    using (var reader = command.ExecuteReader(CommandBehavior.SingleResult))
    {
    using (var reader = command.ExecuteReader(CommandBehavior.SingleResult))
    {
    while (reader.Read())
    yield return converter(reader);
    }
    }

    public static Nullable<T> ValueOrNull<T>(this IDataRecord record, string field) where T : struct
    {
    var value = record[field];
    if (value == DBNull.Value)
    return new Nullable<T>();

    return (T)value;
    }

    public static T ValueOrDefault<T>(this IDataRecord record, string field)
    {
    var value = record[field];
    if (value == DBNull.Value)
    return default(T);

    return (T)value;
    while (reader.Read())
    yield return converter(reader);
    }

    public static long? Long(this IDataRecord record, string column)
    {
    var value = record[column];
    if (value == DBNull.Value)
    return null;

    return (long)value;
    }

    public static string String(this IDataRecord record, string column)
    }

    public static Nullable<T> ValueOrNull<T>(this IDataRecord record, string field) where T : struct
    {
    var value = record[field];
    if (value == DBNull.Value)
    return new Nullable<T>();

    return (T)value;
    }

    public static T ValueOrDefault<T>(this IDataRecord record, string field)
    {
    var value = record[field];
    if (value == DBNull.Value)
    return default(T);

    return (T)value;
    }

    public static long? Long(this IDataRecord record, string column)
    {
    var value = record[column];
    if (value == DBNull.Value)
    return null;

    return (long)value;
    }

    public static string String(this IDataRecord record, string column)
    {
    var value = record[column];
    if (value == DBNull.Value)
    return null;

    return (string)value;
    }

    public static Guid? Guid(this IDataRecord record, string column)
    {
    var value = record[column];
    if (value == DBNull.Value)
    return null;

    return (Guid)value;
    }

    public static DateTime? Date(this IDataRecord record, string column)
    {
    var value = record[column];
    if (value == DBNull.Value)
    return null;

    return (DateTime)value;
    }

    public static int? Int(this IDataRecord record, string column)
    {
    var value = record[column];
    if (value == DBNull.Value)
    return null;

    return (int)value;
    }

    public static bool? Boolean(this IDataRecord record, string column)
    {
    var value = record[column];
    if (value == DBNull.Value)
    return null;

    if (value is bool)
    return (bool)value;

    if (value is int)
    return ((int)value) == 1;

    return Convert.ToBoolean(value);
    }

    public static long? RowVersion(this IDataRecord record, string column)
    {
    object value = record[column];
    if (value == DBNull.Value)
    return null;

    // can't use BitConverter as value coming out is big-endian
    byte[] bytes = (byte[])value;
    long ret = 0;
    for (int i = 0; i < 8; i++)
    {
    var value = record[column];
    if (value == DBNull.Value)
    return null;

    return (string)value;
    }

    public static Guid? Guid(this IDataRecord record, string column)
    {
    var value = record[column];
    if (value == DBNull.Value)
    return null;

    return (Guid)value;
    ret = unchecked((ret << 8) | bytes[i]);
    }

    public static DateTime? Date(this IDataRecord record, string column)
    {
    var value = record[column];
    if (value == DBNull.Value)
    return null;
    return ret;
    }

    return (DateTime)value;
    }
    public static decimal? Decimal(this IDataRecord record, string column)
    {
    var value = record[column];
    if (value == DBNull.Value)
    return null;

    public static int? Int(this IDataRecord record, string column)
    {
    var value = record[column];
    if (value == DBNull.Value)
    return null;
    return (decimal)value;
    }

    return (int)value;
    }
    public static byte[] Binary(this IDataRecord record, string column)
    {
    int idx = record.GetOrdinal(column);
    if (record.IsDBNull(idx))
    return null;

    public static bool? Boolean(this IDataRecord record, string column)
    // copy data into memory
    using (var memory = new MemoryStream())
    {
    var value = record[column];
    if (value == DBNull.Value)
    return null;

    if (value is bool)
    return (bool)value;
    int bufferSize = 4096;
    byte[] buffer = new byte[bufferSize];
    int offset = 0;

    if (value is int)
    return ((int)value) == 1;

    return Convert.ToBoolean(value);
    }

    public static long? RowVersion(this IDataRecord record, string column)
    {
    object value = record[column];
    if (value == DBNull.Value)
    return null;

    // can't use BitConverter as value coming out is big-endian
    byte[] bytes = (byte[])value;
    long ret = 0;
    for (int i = 0; i < 8; i++)
    while (true)
    {
    ret = unchecked((ret << 8) | bytes[i]);
    }
    // read in the data and increment our offset
    long length = record.GetBytes(idx, offset, buffer, 0, bufferSize);
    offset += bufferSize;

    return ret;
    }

    public static decimal? Decimal(this IDataRecord record, string column)
    {
    var value = record[column];
    if (value == DBNull.Value)
    return null;

    return (decimal)value;
    }

    public static byte[] Binary(this IDataRecord record, string column)
    {
    int idx = record.GetOrdinal(column);
    if (record.IsDBNull(idx))
    return null;

    // copy data into memory
    using (var memory = new MemoryStream())
    {
    int bufferSize = 4096;
    byte[] buffer = new byte[bufferSize];
    int offset = 0;

    while (true)
    {
    // read in the data and increment our offset
    long length = record.GetBytes(idx, offset, buffer, 0, bufferSize);
    offset += bufferSize;

    // write the resulting bytes to the memory stream
    memory.Write(buffer, 0, (int)length);
    // write the resulting bytes to the memory stream
    memory.Write(buffer, 0, (int)length);

    // if we didn't read full buffer, then we are likely done
    if (length < bufferSize)
    break;
    }
    return memory.ToArray();
    // if we didn't read full buffer, then we are likely done
    if (length < bufferSize)
    break;
    }

    return memory.ToArray();
    }
    }
    }
    }
    141 changes: 71 additions & 70 deletions DataTranslator.cs
    Original file line number Diff line number Diff line change
    @@ -1,85 +1,86 @@
    public static Func<IDataRecord, T> CreateTranslator<T>(IDataRecord record)
    {
    Type targetType = typeof(T);

    // get all properties that are translated
    var propertyDictionary = targetType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty)
    .Where(p => !Attribute.IsDefined(p, typeof(NotTranslatedAttribute)))
    .ToDictionary(p => p.Name.ToLower());
    public class DataTranslator
    {
    public static Func<IDataRecord, T> CreateTranslator<T>(IDataRecord record)
    {
    // get all properties that are translated
    var propertyDictionary = targetType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty)
    .Where(p => !Attribute.IsDefined(p, typeof(NotTranslatedAttribute)))
    .ToDictionary(p => p.Name.ToLower());

    var recordMappings = new Dictionary<int, PropertyInfo>();
    var recordMappings = new Dictionary<int, PropertyInfo>();

    for (int i = 0; i < record.FieldCount; i++)
    {
    string fieldName = record.GetName(i).ToLower();
    if (propertyDictionary.ContainsKey(fieldName))
    recordMappings.Add(i, propertyDictionary[fieldName]);
    }
    for (int i = 0; i < record.FieldCount; i++)
    {
    string fieldName = record.GetName(i).ToLower();
    if (propertyDictionary.ContainsKey(fieldName))
    recordMappings.Add(i, propertyDictionary[fieldName]);
    }

    // Create Methods to GetValue and check for null from record
    Type dataRecordType = typeof(IDataRecord);
    MethodInfo recordGetValue = dataRecordType.GetMethod("GetValue");
    MethodInfo recordIsDBNull = dataRecordType.GetMethod("IsDBNull");
    // Create Methods to GetValue and check for null from record
    Type dataRecordType = typeof(IDataRecord);
    MethodInfo recordGetValue = dataRecordType.GetMethod("GetValue");
    MethodInfo recordIsDBNull = dataRecordType.GetMethod("IsDBNull");

    // create parameter for record
    ParameterExpression rec = Expression.Parameter(dataRecordType, "record");
    // create parameter for record
    ParameterExpression rec = Expression.Parameter(dataRecordType, "record");

    Expression<Func<IDataRecord, T>> translator = Expression.Lambda<Func<IDataRecord, T>>(
    Expression.MemberInit(Expression<T>.New(targetType),
    recordMappings.Select(mapping =>
    Expression<Func<IDataRecord, T>> translator = Expression.Lambda<Func<IDataRecord, T>>(
    Expression.MemberInit(Expression<T>.New(targetType),
    recordMappings.Select(mapping =>
    {
    // property can handle a null value
    if ((mapping.Value.PropertyType.IsValueType == false) || (mapping.Value.PropertyType.IsGenericType && mapping.Value.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)))
    {
    // property can handle a null value
    if ((mapping.Value.PropertyType.IsValueType == false) || (mapping.Value.PropertyType.IsGenericType && mapping.Value.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)))
    {
    var conversion = Expression.Condition(
    Expression<bool>.Call(rec, recordIsDBNull, Expression<int>.Constant(mapping.Key)),
    Expression.TypeAs(Expression.Constant(null), mapping.Value.PropertyType),
    Expression.TypeAs(Expression.Call(rec, recordGetValue, Expression<int>.Constant(mapping.Key)), mapping.Value.PropertyType)
    );

    return Expression.Bind(mapping.Value, conversion) as MemberBinding;
    }
    var conversion = Expression.Condition(
    Expression<bool>.Call(rec, recordIsDBNull, Expression<int>.Constant(mapping.Key)),
    Expression.TypeAs(Expression.Constant(null), mapping.Value.PropertyType),
    Expression.TypeAs(Expression.Call(rec, recordGetValue, Expression<int>.Constant(mapping.Key)), mapping.Value.PropertyType)
    );

    // handle enumerations
    if (mapping.Value.PropertyType.IsEnum)
    {
    // converts the type returned by the record to that of the underlying type of the enumeration
    Expression<Func<object, Type, object>> converter = (item, toType) => Convert.ChangeType(item, toType);
    return Expression.Bind(mapping.Value, conversion) as MemberBinding;
    }

    var underlyingType = Enum.GetUnderlyingType(mapping.Value.PropertyType);
    var fieldType = record.GetFieldType(mapping.Key);
    // handle enumerations
    if (mapping.Value.PropertyType.IsEnum)
    {
    // converts the type returned by the record to that of the underlying type of the enumeration
    Expression<Func<object, Type, object>> converter = (item, toType) => Convert.ChangeType(item, toType);

    // by default, the value for conversion is what we get from the record.GetValue method call
    Expression valueForConversionExpression = Expression.Call(rec, recordGetValue, Expression<int>.Constant(mapping.Key));
    var underlyingType = Enum.GetUnderlyingType(mapping.Value.PropertyType);
    var fieldType = record.GetFieldType(mapping.Key);

    if (underlyingType != fieldType)
    {
    // the field types don't match, so the value we'll pass to the conversion method will be the result
    // of the Convert.ChangeType method
    valueForConversionExpression = Expression.Invoke(
    converter,
    new Expression[] {
    valueForConversionExpression,
    Expression<Type>.Constant(underlyingType)
    }
    );
    }
    // by default, the value for conversion is what we get from the record.GetValue method call
    Expression valueForConversionExpression = Expression.Call(rec, recordGetValue, Expression<int>.Constant(mapping.Key));

    // return the binding expression
    return Expression.Bind(
    mapping.Value,
    Expression.Convert(
    if (underlyingType != fieldType)
    {
    // the field types don't match, so the value we'll pass to the conversion method will be the result
    // of the Convert.ChangeType method
    valueForConversionExpression = Expression.Invoke(
    converter,
    new Expression[] {
    valueForConversionExpression,
    mapping.Value.PropertyType
    )
    ) as MemberBinding;
    Expression<Type>.Constant(underlyingType)
    }
    );
    }

    // plain ol' struct, just return the conversion
    return Expression.Bind(mapping.Value, Expression.Convert(Expression.Call(rec, recordGetValue, Expression<int>.Constant(mapping.Key)), mapping.Value.PropertyType)) as MemberBinding;
    })
    ), rec
    );
    // return the binding expression
    return Expression.Bind(
    mapping.Value,
    Expression.Convert(
    valueForConversionExpression,
    mapping.Value.PropertyType
    )
    ) as MemberBinding;
    }

    // plain ol' struct, just return the conversion
    return Expression.Bind(mapping.Value, Expression.Convert(Expression.Call(rec, recordGetValue, Expression<int>.Constant(mapping.Key)), mapping.Value.PropertyType)) as MemberBinding;
    })
    ), rec
    );

    return translator.Compile();
    }
    return translator.Compile();
    }
    }
  2. darrenkopp created this gist Feb 21, 2013.
    143 changes: 143 additions & 0 deletions DataReaderExtensions.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,143 @@
    public static IEnumerable<T> Stream<T>(this IDbCommand command, Func<IDataRecord, T> converter)
    {
    using (var reader = command.ExecuteReader(CommandBehavior.SingleResult))
    {
    while (reader.Read())
    yield return converter(reader);
    }
    }

    public static Nullable<T> ValueOrNull<T>(this IDataRecord record, string field) where T : struct
    {
    var value = record[field];
    if (value == DBNull.Value)
    return new Nullable<T>();

    return (T)value;
    }

    public static T ValueOrDefault<T>(this IDataRecord record, string field)
    {
    var value = record[field];
    if (value == DBNull.Value)
    return default(T);

    return (T)value;
    }

    public static long? Long(this IDataRecord record, string column)
    {
    var value = record[column];
    if (value == DBNull.Value)
    return null;

    return (long)value;
    }

    public static string String(this IDataRecord record, string column)
    {
    var value = record[column];
    if (value == DBNull.Value)
    return null;

    return (string)value;
    }

    public static Guid? Guid(this IDataRecord record, string column)
    {
    var value = record[column];
    if (value == DBNull.Value)
    return null;

    return (Guid)value;
    }

    public static DateTime? Date(this IDataRecord record, string column)
    {
    var value = record[column];
    if (value == DBNull.Value)
    return null;

    return (DateTime)value;
    }

    public static int? Int(this IDataRecord record, string column)
    {
    var value = record[column];
    if (value == DBNull.Value)
    return null;

    return (int)value;
    }

    public static bool? Boolean(this IDataRecord record, string column)
    {
    var value = record[column];
    if (value == DBNull.Value)
    return null;

    if (value is bool)
    return (bool)value;

    if (value is int)
    return ((int)value) == 1;

    return Convert.ToBoolean(value);
    }

    public static long? RowVersion(this IDataRecord record, string column)
    {
    object value = record[column];
    if (value == DBNull.Value)
    return null;

    // can't use BitConverter as value coming out is big-endian
    byte[] bytes = (byte[])value;
    long ret = 0;
    for (int i = 0; i < 8; i++)
    {
    ret = unchecked((ret << 8) | bytes[i]);
    }

    return ret;
    }

    public static decimal? Decimal(this IDataRecord record, string column)
    {
    var value = record[column];
    if (value == DBNull.Value)
    return null;

    return (decimal)value;
    }

    public static byte[] Binary(this IDataRecord record, string column)
    {
    int idx = record.GetOrdinal(column);
    if (record.IsDBNull(idx))
    return null;

    // copy data into memory
    using (var memory = new MemoryStream())
    {
    int bufferSize = 4096;
    byte[] buffer = new byte[bufferSize];
    int offset = 0;

    while (true)
    {
    // read in the data and increment our offset
    long length = record.GetBytes(idx, offset, buffer, 0, bufferSize);
    offset += bufferSize;

    // write the resulting bytes to the memory stream
    memory.Write(buffer, 0, (int)length);

    // if we didn't read full buffer, then we are likely done
    if (length < bufferSize)
    break;
    }
    return memory.ToArray();
    }
    }
    }
    85 changes: 85 additions & 0 deletions DataTranslator.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,85 @@
    public static Func<IDataRecord, T> CreateTranslator<T>(IDataRecord record)
    {
    Type targetType = typeof(T);

    // get all properties that are translated
    var propertyDictionary = targetType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty)
    .Where(p => !Attribute.IsDefined(p, typeof(NotTranslatedAttribute)))
    .ToDictionary(p => p.Name.ToLower());

    var recordMappings = new Dictionary<int, PropertyInfo>();

    for (int i = 0; i < record.FieldCount; i++)
    {
    string fieldName = record.GetName(i).ToLower();
    if (propertyDictionary.ContainsKey(fieldName))
    recordMappings.Add(i, propertyDictionary[fieldName]);
    }

    // Create Methods to GetValue and check for null from record
    Type dataRecordType = typeof(IDataRecord);
    MethodInfo recordGetValue = dataRecordType.GetMethod("GetValue");
    MethodInfo recordIsDBNull = dataRecordType.GetMethod("IsDBNull");

    // create parameter for record
    ParameterExpression rec = Expression.Parameter(dataRecordType, "record");

    Expression<Func<IDataRecord, T>> translator = Expression.Lambda<Func<IDataRecord, T>>(
    Expression.MemberInit(Expression<T>.New(targetType),
    recordMappings.Select(mapping =>
    {
    // property can handle a null value
    if ((mapping.Value.PropertyType.IsValueType == false) || (mapping.Value.PropertyType.IsGenericType && mapping.Value.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)))
    {
    var conversion = Expression.Condition(
    Expression<bool>.Call(rec, recordIsDBNull, Expression<int>.Constant(mapping.Key)),
    Expression.TypeAs(Expression.Constant(null), mapping.Value.PropertyType),
    Expression.TypeAs(Expression.Call(rec, recordGetValue, Expression<int>.Constant(mapping.Key)), mapping.Value.PropertyType)
    );

    return Expression.Bind(mapping.Value, conversion) as MemberBinding;
    }

    // handle enumerations
    if (mapping.Value.PropertyType.IsEnum)
    {
    // converts the type returned by the record to that of the underlying type of the enumeration
    Expression<Func<object, Type, object>> converter = (item, toType) => Convert.ChangeType(item, toType);

    var underlyingType = Enum.GetUnderlyingType(mapping.Value.PropertyType);
    var fieldType = record.GetFieldType(mapping.Key);

    // by default, the value for conversion is what we get from the record.GetValue method call
    Expression valueForConversionExpression = Expression.Call(rec, recordGetValue, Expression<int>.Constant(mapping.Key));

    if (underlyingType != fieldType)
    {
    // the field types don't match, so the value we'll pass to the conversion method will be the result
    // of the Convert.ChangeType method
    valueForConversionExpression = Expression.Invoke(
    converter,
    new Expression[] {
    valueForConversionExpression,
    Expression<Type>.Constant(underlyingType)
    }
    );
    }

    // return the binding expression
    return Expression.Bind(
    mapping.Value,
    Expression.Convert(
    valueForConversionExpression,
    mapping.Value.PropertyType
    )
    ) as MemberBinding;
    }

    // plain ol' struct, just return the conversion
    return Expression.Bind(mapping.Value, Expression.Convert(Expression.Call(rec, recordGetValue, Expression<int>.Constant(mapping.Key)), mapping.Value.PropertyType)) as MemberBinding;
    })
    ), rec
    );

    return translator.Compile();
    }