实体框架覆盖默认属性约定以忽略属性

时间:2016-04-13 13:23:18

标签: c# .net entity-framework

我正在重写遗留系统以使用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仍然会尝试将属性映射到不存在的数据库字段,并抛出无效列异常。

有没有人有其他想法?

1 个答案:

答案 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);
                        }
                    }
                });