Why there is no EF Core OfType(Type type) method?

.net-core entity-framework-core

Question

I currently use EF Core 3.0. So, I want to realize TPH model data selection through the base table requesting. Let's see the example:

public class BaseClass
{
   public int Base {get;set;}
}

public class Foo : BaseClass
{
   public int FooMember {get;set;}
}

public class Bar : BaseClass
{
  public int BarMember {get;set;}
}

public DbSet<BaseClass> dbSet {get;set;}

And I want to implement code like this:

var getInheritedSet = dbSet.OfType(typeIStronglyNeed);

But I can only do something like this:

var getInheritedSet1 = dbSet.OfType<Foo>;
var getInheritedSet2 = dbSet.OfType<Bar>;

Could you explain why EF Core 3.0 has no OfType(Type type) but only OfType<TType>()?

And the second question - how is it possible to get inherited data types from DbSet?

Thank you.

1
2
9/15/2019 12:23:40 AM

Accepted Answer

The generic method OfType<T> is a standard LINQ method which EF Core supports.

There is no standard OfType(Type) method and EF Core designers didn't find a reason of implementing such custom EF Core specific extension.

But it's not hard to be implemented. TPH (and other future database inheritance strategies) are supported in LINQ to Entities queries by is, as and cast operators. So what you need is the equivalent of

Where((BaseClass e) => e is some_type)

Such expression cannot be created at compile time, but can easily be created using the Expression class methods (in particular Expression.TypeIs) like this:

public static IQueryable<T> OfType<T>(this IQueryable<T> source, Type type)
{
    var parameter = Expression.Parameter(typeof(T), "e");
    var body = Expression.TypeIs(parameter, type);
    var predicate = Expression.Lambda<Func<T, bool>>(body, parameter);
    return source.Where(predicate);
}

And the second question - how is it possible to get inherited data types from DbSet?

EF Core metadata is exposed through DbContext.Model property. You can use FindEntityType to get the IEntityType describing the entity type

var entityType = dbContext.Model.FindEntityType(typeof(BaseClass));

and now there are a lot of available methods regarding inheritance like GetDerivedTypes, GetDerivedTypesInclusive, GetDirectlyDerivedTypes, GetConcreteDerivedTypesInclusive etc. The last one can be used to retrieve the whole TPH hierarchy excluding the abstract types. And also GetDiscriminatorProperty and GetDiscriminatorValue to get the discriminator column name, type and value for each entity in the TPH. For instance

var discriminatorProperty = entityType.GetDiscriminatorProperty();
var typeInfo = entityType
    .GetConcreteDerivedTypesInclusive()
    .Select(t => new
    {
        Type = t,
        DiscriminatorValue = t.GetDiscriminatorValue()
    })
    .ToList();
2
9/16/2019 12:00:35 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow