我正在尝试使用反射在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 });