使用反射来自动化EF5 Code First DbModelBuilder



我正在尝试使用反射在OnModelCreating中自动生成DbModelBuilder对象。

我有许多继承自基类的类:Enumeration在数据库中,我希望能够设置这些表的Id所以在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);
}

你的代码中有两个错误,第一个是这一行:

//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)。假设someeclassid是int类型,将该行更改为:

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

相关内容

  • 没有找到相关文章

最新更新