Casting to a derived type in a LINQ to Entities query with Table Per Hierarchy inheritance

I have a LINQ to entities model with Table Per Hierarchy inheritance. I have a query over the base type, and I want to do specific type-dependent logic. For example:

IQueryable<BaseType> base = ...

// this works fine
var result = base.Select(b => b is DerivedType1 ? 1 : 2).ToList();

// this doesn't compile to SQL
var result2 = base.Select(b => b is DerivedType1 ? ((DerivedType1)b).DerivedProperty : null).ToList();

Is there any way to do something like this without processing IQueryables of each derived type separately:

// I'd rather not do this:
var resultA = base.OfType<DerivedType1>().Select(d => d.DerivedProperty);
var resultB = base.OfType<DerivedType2>().Select(d => default(int?));
var result = resultA.Concat(resultB).ToList();

Answers


Direct casting to an entity type like (DerivedType1)b isn't supported with LINQ-to-Entities but the as operator (b as DerivedType1) is, hence you could try:

var result2 = base
    .Select(b => b is DerivedType1
        ? (b as DerivedType1).DerivedProperty
        : null)
    .ToList();

You could have a method on your base type that's overridden in your derived types to provide the relevant property value.

public class MyBaseClass
{
    public virtual int GetSomething()
    {
        throw new NotImplementedException();
    }
}

public class MyDerivedClass1 : MyBaseClass
{
    public int SomeProperty { get; set; }

    public override int GetSomething()
    {
        return this.SomeProperty;
    }
}

public class MyDerivedClass2 : MyBaseClass
{
    public int SomeOtherProperty { get; set; }

    public override int GetSomething()
    {
        return this.SomeOtherProperty;
    }
}

Then you could:

var result = base.Select(b => b.GetSomething()).ToList();

Try this, I have never done anything with needing to do this kind of this but this should do it. Also if you use base, first of all don't because it is a keyword but if you must, use @base the @ in front of the name denotes that it is not used as a keyword.

var resultA = base.Select(aVar =>
                            (aVar is DerivedType1) ?
                                (DerivedType)(((DerivedType1)aVar).DerivedProperty)
                                :
                                (DerivedType)(default(int?))
                        ).ToList();

OfType<DerivedType1>() 

will return an IEnumerable, if possible, try to change to base-type to IEnumerable instead of IQueryable, you might en up in some SQL restrictions when using IQueryable.

That is of course if you are not actually quering a database?


You can use EntityFramework.Extended to improve the performance of the query instead of doing 2 round trips to DB.

var resultA = base.OfType<DerivedType1>().Select(d => d.DerivedProperty).Future();
var resultB = base.OfType<DerivedType2>().Select(d => default(int?)).Future();
var result = resultA.Concat(resultB).ToList();

In this case only one round trip to bd is executed. This framework is very useful for many other things int EF


Need Your Help

How to stretch images with no antialiasing

javascript css image image-manipulation

So I ran across this recently: http://www.nicalis.com/index.php

Input fields hold previous values only if validation failed

jsf popup richfaces jsf-1.2 ajax4jsf

I came up with a strange problem. I tried to isolate the problem so following is my simplified code.