Более разумный API-интерфейс Entity Framework Codefirst

Мне нужно использовать Sql Server "datetime2" типа во всех DateTime и DateTime? свойства всех объектов объекта. Обычно это делается с использованием свободного API:

modelBuilder.Entity<Mail>().Property(c => c.SendTime).HasColumnType("datetime2");

Однако я бы предпочел НЕ делать это вручную для каждого поля DateTime в каждом типе сущности. (У меня нет общего базового типа, где все свойства DateTime могут быть размещены, поскольку свойства DateTime являются специфичными для типов сущностей, где они определены).

Короткий вопрос: каковы мои варианты?

Длинный вопрос: я рассматривал возможность использования рефлексии и сделал попытку, но это стало очень беспорядочным, поскольку кажется, что свободный API не подходит для такого рода работ, потому что я должен был назвать общие беглое API-методы через отражение, Вот моя грязная попытка:

    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        var genericEntityMethod = modelBuilder.GetType().GetMethod("Entity");
        var entityTypes = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.IsClass && !t.IsAbstract && t.GetInterface("IEntity") != null);
        foreach (var t in entityTypes) {
            var props = t.GetProperties().Where(p => 
                p.GetSetMethod() != null && 
                p.GetGetMethod() != null && 
                (p.PropertyType == typeof (DateTime) ||  
                p.PropertyType == typeof(DateTime?)));
            foreach (var propertyInfo in props) {
                var entityMethod = genericEntityMethod.MakeGenericMethod(t.GetType());
                var entityTypeConfiguration = entityMethod.Invoke(modelBuilder,null);
                var lambdaExpression = Expression.Lambda(Expression.MakeMemberAccess(Expression.Parameter(t), propertyInfo), Expression.Parameter(t));

                //var propertyMethod = entityTypeConfiguration.GetType().GetMethod("Property");  // Cant get this to work
                var propertyMethods = entityTypeConfiguration.GetType().GetMethods().Where(m => m.ReturnType == typeof(DateTimePropertyConfiguration)).ToList();
                var propertyMethod = propertyInfo.PropertyType == typeof (DateTime) ? propertyMethods[0] : propertyMethods[1];

               var dateTimePropertyConfiguration = propertyMethod.Invoke(entityTypeConfiguration, new object[] {lambdaExpression});
                var hasColumnTypeMethod = entityTypeConfiguration.GetType().GetMethod("HasColumnType");
                hasColumnTypeMethod.Invoke(dateTimePropertyConfiguration, new object[]{ "datetime2" });
            }
        }
        base.OnModelCreating(modelBuilder);
    }

В этой строке не выполняется:

                   var dateTimePropertyConfiguration = propertyMethod.Invoke(entityTypeConfiguration, new object[] {lambdaExpression});

с этой ошибкой (Entities.Order - это один из объектов моего объекта, обладающий свойством DateTime):

Object of type 'System.Linq.Expressions.Expression`1[System.Func`2[Entities.Order,System.Nullable`1[System.DateTime]]]' cannot be converted to type 'System.Linq.Expressions.Expression`1[System.Func`2[System.RuntimeType,System.Nullable`1[System.DateTime]]]

Может ли кто-нибудь помочь мне с этим рефлексивным подходом или лучше, показать мне более простой способ избежать необходимости вручную писать много свободного материала api?

Ответ 1

Существует подход гораздо лучше. К сожалению, этот подход основан на пользовательских соглашениях, которые будут доступны в EF6. Вы можете попробовать EF6 Alpha 2 и поиграть с собственными соглашениями - прохождение содержит пример с вашим точным требованием.

Чтобы решить вашу проблему с помощью рефлексии, отметьте эту статью в блоге. Он описывает код для генерации отображений с отражением (должен быть связан проект с открытым исходным кодом).