5

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
}
user3012633
  • 464
  • 5
  • 6
  • Can you provide some context around why this is a problem? In other words, how are you saving the data that makes you want to ignore the properties in this manner? – Brendan Green Aug 05 '15 at 04:59
  • 1
    having ignored properties only in viewmodel could be possible workaround here.include necessary properties in model and have all properties in view model (with ignored properties) – ManirajSS Aug 05 '15 at 05:04
  • @BrendanGreen I'm working with the ebay SDK. There are a lot of classes, they have lots of properties none of which have keys specified. I only want to save a small amount of data to the database. It would save a lot of time to only be able to choose what I want rather than have to ignore everything I don't want. – user3012633 Aug 05 '15 at 05:14
  • does that mean you have just modelled your database directly after the SDK? Maybe I'm missing something here, but if you want to ignore all of these properties, then just remove them from your data model. Alternatively, as mentioned (assuming this is a web app), use a view model to pass data between the controller and the view, and you won't have to deal with the unwanted fields at all. – Brendan Green Aug 05 '15 at 05:24
  • @BrendanGreen Yes I have modelled the database after the SDK. Sorry, I am new to EF, what do you mean when you say remove the ones I don't want from my data model? – user3012633 Aug 05 '15 at 05:47
  • Use two class, one model class with only the properties you want to store, and a ViewModel class with all the properties. don't persist the ViewModel just instanciate it with your model. (and inversement) – Emmanuel M. Aug 05 '15 at 07:47

1 Answers1

7

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.

Taher Rahgooy
  • 6,528
  • 3
  • 19
  • 30