Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework - Code First - Ignore all properties except those specified

I am working with some large classes that have lots of properties, and I don't want to have to ignore all the properties I don't want to save to the database. Rather, is there anyway to ignore all properties and specify only the ones I want?

So instead of this

protected override void OnModelCreating(DbModelBuilder mb)
{
    // code to ignore properties i don't want one at a time, i.e.
    mb.Entity<Person>().Ignore(i => i.Name);
    mb.Entity<Person>().Ignore(i => i.Birthday);
}

I would have

protected override void OnModelCreating(DbModelBuilder mb)
{
    // code to ignore all properties
    // code to include only properties I want
}
like image 355
user3012633 Avatar asked Aug 05 '15 04:08

user3012633


1 Answers

You can use reflection in order to call Ignore method for all properties except the ones that you need. It can be achieved by creating an extension method like this:

public static class EntityTypeConfigurationExtentions
{
    public static EntityTypeConfiguration<TEntityType> IgnoreAllExcept<TEntityType>
       (this EntityTypeConfiguration<TEntityType> t, params string[] except)
        where TEntityType:class
    {
        var type = typeof(TEntityType);
        var properties = type.GetProperties();
        var dontIgnore = except ?? new string[0];
        //Here you can add more constraints on the class properties
        var toIgnore = properties.Where(x => !except.Contains(x.Name) && 
                                             x.SetMethod != null).ToList();
        foreach (var name in toIgnore)
        {
            var selector = GetIgnoreExpression<TEntityType>(name);
            MethodInfo genericMethod = GetIgnoreMethod<TEntityType>(name.PropertyType);
            genericMethod.Invoke(t, new object[] { selector });
        }
        return t;
    }
    private static MethodInfo GetIgnoreMethod<TEntityType>(Type propType)
    {
        var t = typeof(EntityTypeConfiguration<>);
        t = t.MakeGenericType(typeof(TEntityType));
        MethodInfo method = t.GetMethod("Ignore");
        MethodInfo genericMethod = method.MakeGenericMethod(propType);
        return genericMethod;
    }
    //This method creates the 'x=>x.PropertyName' expression for Ignore method
    private static Expression GetIgnoreExpression<TEntityType>(PropertyInfo prop)
    {
        ParameterExpression arg = Expression.Parameter(typeof(TEntityType), "x");
        MemberExpression property = Expression.Property(arg, prop.Name);
        var exp = Expression.Lambda(property, new ParameterExpression[] { arg });
        return exp;
    }
}

Firstly we extract all properties of the class that has a setter(if you have more constraints, you most provide them there) and do not belong to the exception list, then we call Ignore method of the EntityTypeConfiguration<TEntityType> class for each property, in order to ignore that property.

To invoke the Ignore method, we need to obtain the generic class type, and then find the Ignore method of the class, then provide the generic type of the Ignore method, and finally invoke it by the appropriate argument.

The argument of the Ignore method is obtained by creating a lambda expression that selects the desired property from the TEntityType class.

After defining this extension class, you can call the IgnoreAllExcept like this:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
       modelBuilder.Entity<TestClass>().IgnoreAllExcept("Id", "Name");
}

You can also improve this method, by changing the except parameter to expressions that selects the properties of the class.

like image 172
Taher Rahgooy Avatar answered Oct 30 '22 22:10

Taher Rahgooy