Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I find all DbSets whose generic types derive from a given base type?

How can I get a List of all DbSets where the contained type derives from IncomingServiceOrderBase?

I can use reflection to get the all the DbSets, but how do I filter it down to just those that contain a derived type?

Context

public class MyContext : DbContext
{
    public DbSet<BuildingOrder> BuildingOrders { get; set; }
    public DbSet<DeliveryOrder> DeliveryOrders { get; set; }
    public DbSet<RetailAssemblyOrder> RetailAssemblyOrders { get; set; }
}

Model

public class BuildingOrder : IncomingManufacturedProductOrderBase { }
public class DeliveryOrder : IncomingServiceOrderBase { }
public class RetailAssemblyOrder : IncomingServiceOrderBase { }
like image 509
Benjamin Avatar asked May 08 '12 00:05

Benjamin


2 Answers

You can do somehing like this:

var sets =
    from p in typeof(MyContext).GetProperties()
    where p.PropertyType.IsGenericType
    && p.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>)
    let entityType = p.PropertyType.GetGenericArguments().First()
    where typeof(IncomingServiceOrderBase).IsAssignableFrom(entityType)
    select p.Name;

(this returns the names of the properties; if you want the actual DbSet instances, replace p.Name with p.GetValue(context, null))

like image 148
Thomas Levesque Avatar answered Oct 23 '22 05:10

Thomas Levesque


typeof(BaseType).IsAssignableFrom(DerivedType). It'll return true/false. See http://msdn.microsoft.com/en-us/library/system.type.isassignablefrom.aspx

To turn DbSet<T> into T (so you can do this comparison) take each property's type and do something like this:

    public static Type GetGenericBaseType( this Type Type ) {
        if ( Type == null ) {
            throw new ArgumentNullException( "Type" );
        }
        if ( !Type.IsGenericType ) {
            throw new ArgumentOutOfRangeException( "Type", Type.FullName + " isn't Generic" );
        }
        Type[] args = Type.GetGenericArguments();
        if ( args.Length != 1 ) {
            throw new ArgumentOutOfRangeException( "Type", Type.FullName + " isn't a Generic type with one argument -- e.g. T<U>" );
        }
        return args[0];
    }
like image 31
robrich Avatar answered Oct 23 '22 07:10

robrich