2013-05-15 8 views
1

Я пытаюсь автоматизировать объект DbModelBuilder в OnModelCreating с использованием отражения.Использование отражения для автоматизации EF5 Code First DbModelBuilder

У меня есть несколько классов, которые наследуют от базового класса: Перечень В базе данных я хочу, чтобы иметь возможность установить идентификаторы этих таблиц так в OnModelCreating я называю

modelBuilder.Entity<SomeClass>() 
      .Property(sc => sc.SomeClassId) 
      .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); 

Я хотел бы автоматизировать это с помощью рефлексии, потому что, если я забыл сделать это, когда модель применяется к базе данных, я должен ее удалить и начать заново.

Я знаю, что могу поместить атрибут в мою модель класса, но я не хочу его там.

Здесь код. По какой-то причине он терпит неудачу, когда я пытаюсь вызвать свой общий метод. У кого-нибудь есть предложения?

//Get all of my Models/Tables that I want to be able to specify a proimary key for. 

var enumerationPropertyInfos = thisDbContext 
    .GetType() 
    .GetProperties(); 
    .Where(p => p.PropertyType.IsGenericType 
     && p.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>) 
     && p.PropertyType.GetGenericArguments().First().BaseType == typeof(MyEnumerationBase)); 


foreach (PropertyInfo pi in enumerationPropertyInfos) 
{ 
    //modelBuilder.Entity<SomeClass>() 
    var config = modelBuilder.GetType() 
     .GetMethod("Entity") 
     .MakeGenericMethod(pi.PropertyType) 
     .Invoke(modelBuilder, null); 

    //Prepare .Property(...) 
    var property = config.GetType().GetMethods().Where(m => m.Name == "Property").First(); 

    var propertyExpression = typeof(Expression<>) 
     .MakeGenericType(typeof(Func<,>) 
     .MakeGenericType(pi.PropertyType, typeof(int))); 

    //Prepare e => e.SomeClassId 
    var paramEx = Expression.Parameter(pi.PropertyType.GetGenericArguments().First(), "e"); 
    var lambdaEx = Expression.Lambda(Expression.Property(paramEx, pi.PropertyType.GetGenericArguments().First().Name + "Id"), paramEx); 

    //Execute .Property(e => e.SomeClassId) 
    PrimitivePropertyConfiguration propertyResult = (PrimitivePropertyConfiguration)property 
     .MakeGenericMethod(typeof(Expression)) 
     .Invoke(config, new[] { lambdaEx }); 

    propertyResult.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); 
} 

ответ

2

У вас есть две ошибки в коде, первый это строка:

//modelBuilder.Entity<SomeClass>() 
var config = modelBuilder.GetType() 
    .GetMethod("Entity") 
    .MakeGenericMethod(pi.PropertyType) 
    .Invoke(modelBuilder, null); 

Поскольку это эквивалентно:

modelBuilder.Entity<DbSet<SomeClass>>(); 

изменить его на:

var config = modelBuilder.GetType() 
    .GetMethod("Entity") 
    .MakeGenericMethod(pi.PropertyType.GetGenericArguments().First()) 
    .Invoke(modelBuilder, null); 

Вторая ошибка в этой строке:

var propertyResult = (PrimitivePropertyConfiguration)property 
    .MakeGenericMethod(typeof(Expression)) 
    .Invoke(config, new[] { lambdaEx }); 

Вам необходимо пройти тип SomeClassId в качестве общего параметра Property() метод, но вы передаете typeof(Expression) вместо этого. Предполагая, что SomeClassId имеет тип int, измените строку на:

var propertyResult = (PrimitivePropertyConfiguration)property 
    .MakeGenericMethod(typeof(int)) 
    .Invoke(config, new[] { lambdaEx }); 
Смежные вопросы