I have a simple extension method for filtering a LINQ IQueryable by tags. I'm using this with LINQ to Entities with an interface of:
public interface ITaggable
{
    ICollection<Tag> Tags { get; } 
}
The following does not work, returning IQueryable<ITaggable> instead of IQueryable<T>:
public static IQueryable<T> WhereTagged<T>(this IQueryable<T> set, string tag) where T:ITaggable
    {
        return set.Where(s=>s.Tags.Any(t=>t.Name.ToLower() == tag.ToLower()));
    }
This leads to a LINQ to Entities cast exception:
"Unable to cast the type 'ReleaseGateway.Models.Product' to type 'ReleaseGateway.Models.ITaggable'. LINQ to Entities only supports casting Entity Data Model primitive types." (System.NotSupportedException) A System.NotSupportedException was caught: "Unable to cast the type 'Project.Models.Product' to type 'Project.Models.ITaggable'. LINQ to Entities only supports casting Entity Data Model primitive types."
It works without the constraint like this, but I have to explicitly declare the type T in my application code:
public static IQueryable<T> WhereTagged<T>(this IQueryable<ITaggable> set, string tag)
{
    return set.Where(s=>s.Tags.Any(t=>t.Name.ToLower() == tag.ToLower())).Cast<T>();
}
Question: Why does the type constraint cast the return type? Can I rewrite this to take advantage of inferring the type from the extension method caller?
I suspect that the problem arises from the call to s.Tags. Because s is a Product, but you're calling ITaggable.Tags, the expression that gets generated looks more like:
set.Where(s=>((ITaggable)s).Tags.Any(...))
That just confuses Entity Framework. Try this:
((IQueryable<ITaggable>)set)
    .Where(s=>s.Tags.Any(t=>t.Name.ToLower() == tag.ToLower()))
    .Cast<T>();
Since IQueryable is a covariant interface, this will treat the set as an IQueryable<ITaggable>, which should work since your second example basically does exactly the same thing.
I was looking for the same answer and not being satisfied with the syntactic cleanliness of the answers provided, I kept looking and found this post.
tl;dr; - add class to your constraints and it works.
LINQ to Entities only supports casting EDM primitive or enumeration types with IEntity interface
public static IQueryable<T> WhereTagged<T>(this IQueryable<T> set, string tag)
    where T: class, ITaggable
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With