我正在重写遗留系统以使用Entity Framework。旧系统具有实体,其中一半属性映射到DB列而另一半不映射。要指示必须映射属性,该属性使用[Field]属性进行修饰。所有其他属性都被忽略了。
这与EF的做法相反。按照惯例,EF使用getter和setter将所有公共属性映射到DB字段,除非使用[NotMapped]数据注释修饰属性,或者使用模型创建时的流畅API为该属性调用Ignore。
我想覆盖EF约定作为旧系统。即忽略没有FieldAttribute的属性。我知道这可以通过将[NotMapped]添加到所有属性来完成,但我正在寻找一种动态执行此操作的方法,以便我不必更改每个实体(有数百个)
我没有删除或覆盖的系统约定,我可以看到
https://msdn.microsoft.com/en-us/library/system.data.entity.modelconfiguration.conventions.aspx
我已经尝试使用以下代码使用反射调用ignore而没有运气:
modelBuilder.Properties().Configure((configuration) =>
{
var attributes = configuration.ClrPropertyInfo.GetCustomAttributes(inherit: false);
var fieldAttribute = attributes.FirstOrDefault(x => x.GetType() == typeof(FieldAttribute) || x.GetType() == typeof(KeyAttribute));
if (fieldAttribute == null)
{
var entityMethod = modelBuilder.GetType().GetMethod("Entity");
var entityConfiguration = entityMethod.MakeGenericMethod(configuration.ClrPropertyInfo.ReflectedType).Invoke(modelBuilder, new object[] { });
MethodInfo ignoreMethod = entityConfiguration.GetType()
.GetMethod("Ignore")
.MakeGenericMethod(configuration.ClrPropertyInfo.PropertyType);
var parameter = Expression.Parameter(configuration.ClrPropertyInfo.ReflectedType);
var memberExpression = Expression.Property(parameter, configuration.ClrPropertyInfo.Name);
var lambdaExpression = Expression.Lambda(memberExpression, parameter);
ignoreMethod.Invoke(entityConfiguration, new[] { lambdaExpression });
}
});
这看起来很有效,因为该属性已添加到实体配置的忽略列表中。但是EF仍然会尝试将属性映射到不存在的数据库字段,并抛出无效列异常。
有没有人有其他想法?
答案 0 :(得分:1)
我找到了问题的解决方案。如果我来自TypeConventionConfiguration而不是PropertyConventionConfiguration它可以工作。我上面的代码中可能有一些错误。这样我需要少用反射......
modelBuilder.Types().Configure((entityConfiguration) =>
{
const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly;
foreach (var propertyInfo in entityConfiguration.ClrType.GetProperties(bindingFlags))
{
var attributes = propertyInfo.GetCustomAttributes(inherit: false);
var fieldAttribute = attributes.FirstOrDefault(x => x.GetType() == typeof(FieldAttribute) || x.GetType() == typeof(KeyAttribute));
if (fieldAttribute == null)
{
entityConfiguration.Ignore(propertyInfo);
}
}
});