1

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

我有许多从基类继承的类:枚举在数据库中我希望能够设置这些表的 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);
}
4

1 回答 1

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 });
于 2013-05-15T05:35:12.810 回答