using System.Collections.Generic;
using System.Linq.Expressions;
using System.Diagnostics;
public static void Main()
var dataTable = whatever.ToDataTable(
whatever.Property(r=>r.Id).AsPrimaryKey().Named("item_id"),
whatever.Property(r=>r.Name).AsOptional().Named("item_name"),
whatever.Property(r=>r.Foo).Ignore()
public static class EnumerableExtensions
public static DataTable ToDataTable<TEntityType>(this IEnumerable<TEntityType> enumerable,
params StructuralTypeConfig<TEntityType>[] configs)
where TEntityType : class
var dt = new DataTable();
(from p in typeof (TEntityType).GetProperties()
join cp in configs.Select((cfgItem, index)=> new { index, item = cfgItem }) on p.Name equals cp.item.PropertyName into groupJoin
from cj in groupJoin.DefaultIfEmpty()
let index = cj == null ? int.MaxValue : cj.index
select new { index, Property = p, Config = (cj == null ? null : cj.item) }).ToList();
foreach (var p in orderedProperties)
var typetoUse = Nullable.GetUnderlyingType(p.Property.PropertyType) ?? p.Property.PropertyType;
var columnName = p.Property.Name;
columnName = p.Config.ColumnName ?? columnName;
typetoUse = p.Config.Type ?? typetoUse;
dt.Columns.Add(columnName, typetoUse);
foreach (var entityRow in enumerable)
orderedProperties.Where(op=>op.Config == null || !op.Config.Ignored ).Select(prop =>
if (prop.Config != null && prop.Config.ValueGetter != null)
return prop.Config.ValueGetter(prop.Property.GetValue(entityRow));
return prop.Property.GetValue(entityRow);
dt.LoadDataRow(values, LoadOption.OverwriteChanges);
public static StringColumnConfig<TEntityType> Property<TEntityType>(this IEnumerable<TEntityType> enumerable,
Expression<Func<TEntityType, string>> expr)
return new StringColumnConfig<TEntityType>(expr.GetMember());
public static StructuralTypeConfig<TEntityType> Property<TEntityType>(this IEnumerable<TEntityType> enumerable,
Expression<Func<TEntityType, bool?>> expr)
return new StructuralTypeConfig<TEntityType>(expr.GetMember());
public static StructuralTypeConfig<TEntityType> Property<TEntityType>(this IEnumerable<TEntityType> enumerable,
Expression<Func<TEntityType, bool>> expr)
return new StructuralTypeConfig<TEntityType>(expr.GetMember());
public static StructuralTypeConfig<TEntityType> Property<TEntityType>(this IEnumerable<TEntityType> enumerable,
Expression<Func<TEntityType, int?>> expr)
return new StructuralTypeConfig<TEntityType>(expr.GetMember());
public static StructuralTypeConfig<TEntityType> Property<TEntityType>(this IEnumerable<TEntityType> enumerable,
Expression<Func<TEntityType, int>> expr)
return new StructuralTypeConfig<TEntityType>(expr.GetMember());
public static StructuralTypeConfig<TEntityType> Property<TEntityType>(this IEnumerable<TEntityType> enumerable,
Expression<Func<TEntityType, long>> expr)
return new StructuralTypeConfig<TEntityType>(expr.GetMember());
public static StructuralTypeConfig<TEntityType> Property<TEntityType>(this IEnumerable<TEntityType> enumerable,
Expression<Func<TEntityType, long?>> expr)
return new StructuralTypeConfig<TEntityType>(expr.GetMember());
public static StructuralTypeConfig<TEntityType> Property<TEntityType>(this IEnumerable<TEntityType> enumerable,
Expression<Func<TEntityType, float?>> expr)
return new StructuralTypeConfig<TEntityType>(expr.GetMember());
public static StructuralTypeConfig<TEntityType> Property<TEntityType>(this IEnumerable<TEntityType> enumerable,
Expression<Func<TEntityType, float>> expr)
return new StructuralTypeConfig<TEntityType>(expr.GetMember());
public static StructuralTypeConfig<TEntityType> Property<TEntityType>(this IEnumerable<TEntityType> enumerable,
Expression<Func<TEntityType, DateTime>> expr)
return new StructuralTypeConfig<TEntityType>(expr.GetMember());
public static StructuralTypeConfig<TEntityType> Property<TEntityType, T>(
this IEnumerable<TEntityType> enumerable,
Expression<Func<TEntityType, T>> expr)
return new StructuralTypeConfig<TEntityType>(expr.GetMember());
private static PropertyInfo GetMember<TEntityType, T>(this Expression<Func<TEntityType, T>> expr)
if (expr == null) throw new ArgumentNullException("expr");
if (expr.Body == null) throw new InvalidOperationException();
var mex = expr.Body as MemberExpression;
if (mex == null) throw new InvalidOperationException();
return (PropertyInfo)mex.Member;
[DebuggerDisplay("{ColumnName}")]
public class StructuralTypeConfig<TEntityType>
public bool Optional { get; private set; }
public bool PrimaryKey { get; private set; }
public bool Ignored { get; private set; }
public string ColumnName { get; private set; }
public PropertyInfo PropertyInfo { get; private set; }
public string PropertyName { get; private set; }
public Type Type { get; private set; }
public Func<object, object> ValueGetter { get; set; }
public StructuralTypeConfig(PropertyInfo property)
ColumnName = property.Name;
PropertyName = property.Name;
public StructuralTypeConfig<TEntityType> AsOptional(bool value = true)
public StructuralTypeConfig<TEntityType> AsPrimaryKey(bool value = true)
public StructuralTypeConfig<TEntityType> Named(string value)
public StructuralTypeConfig<TEntityType> Ignore(bool value = true)
public StructuralTypeConfig<TEntityType> Get<T>(Func<object, object> valueGetter)
ValueGetter = valueGetter;
public class StringColumnConfig<TEntityType> : StructuralTypeConfig<TEntityType>
public int MaxLength { get; private set; }
public int MinLength { get; private set; }
public StringColumnConfig(PropertyInfo property)
public StructuralTypeConfig<TEntityType> HasMaxLength(int value)
public StructuralTypeConfig<TEntityType> HasMinLength(int value)