C# – Where is the cast here? LINQ to Entities only supports casting Entity Data Model primitive types

centity-framework

I have a number of entity framework tables that I have made support an interface IHistoricEntity using their parital classes. IHistoricEntity has ActiveTo Datetime? property.

// Auto generated LINQ to Entities domain service:
[EnableClientAccess()]
public partial class ProductService : LinqToEntitiesDomainService<ProductDBEntities>
{
    public IQueryable<ANALYSIS_CODES> GetANALYSIS_CODES()
    {
        return this.ObjectContext.ANALYSIS_CODES;
    }
 ...
}

// My Partial class to add interface
public partial class ANALYSIS_CODES : IHistoricEntity
{}

I am trying to refactor this working code to a method:

List<ANALYSIS_CODE> filtered = (from rec in ps.GetANALYSIS_CODES() where rec.ActiveTo == null select rec).ToList()

Like so:

private List<T> Filter<T>(IQueryable<T> queryable) where T : IHistoricEntity
{
    return (from rec in queryable where rec.ActiveTo == null select rec).ToList();
}

// called like this:
List<ANALYSIS_CODE> filtered = Filter(ps.GetANALYSIS_CODES());

This gives this exception on the ToList:

Unable to cast the type 'ANALYSIS_CODES' to type 'IHistoricEntity'. LINQ to Entities only supports casting Entity Data Model primitive types.

But where have I asked it to cast to an IHistoricEntity? I have mearly said that T must support IHistoricEntity.

Best Answer

rec.ActiveTo refers to a property defined in your interface. Therefore Linq needs to cast rec to IHistoricEntity before being able to access that property.

Don't be fooled by the exception being raised in .ToList(): the Linq query is only evaluated and executed when the records are needed, in this case, when the collection is to be transformed into a List<>.

Update: I verified @hvd's comment, and indeed, adding a where T: class clause changes the Linq expression from

System.Collections.Generic.List`1[MyType]
    .Where(x => (Convert(x).ActiveTo == Convert(null)))

to

System.Collections.Generic.List`1[MyType]
    .Where(x => (x.ActiveTo == Convert(null)))