CuanP
CuanP

Reputation: 51

Entity Framework override default property convention to ignore properties

I am rewriting a legacy system to use Entity Framework. The old system had entities where half of the properties were mapped to DB columns and the other half not. To indicate that a property had to be mapped, the property was decorated with a [Field] attribute. All other properties were ignored.

This is the opposite of what EF does. By convention, EF maps all public properties with a getter and setter to a DB field unless the property is decorated with [NotMapped] data annotation or Ignore is called on for that property using the fluent API on model creating.

I want to override the EF convention to work as the old system. ie Ignore properties that do not have the FieldAttribute. I know that this could be done by adding [NotMapped] to all the properties, but I'm looking for a way to do this dynamically so that i don't have to change every single entity (there are hundreds)

There's not system convention to remove or override for this that i can see

https://msdn.microsoft.com/en-us/library/system.data.entity.modelconfiguration.conventions.aspx

I've tried the following code to call ignore using reflection with no luck :

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

This looks like it works, as the property is added to the ignore list of the entity configuration. But EF still tries to map the property to a non existent DB field and throws an Invalid column exception.

Does anyone have any other ideas?

Upvotes: 3

Views: 1290

Answers (1)

CuanP
CuanP

Reputation: 51

I found a solution to the problem. If i come at this from the TypeConventionConfiguration instead of the PropertyConventionConfiguration it works. I probably had some bug in my code above. This way i need to use less reflection...

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

Upvotes: 2

Related Questions