I have a generic IQueryable of a concrete class:
IQueryable<Person> result = GetAllEmployees(); //returns IQueryable<Employee>
If I return result
in a service-call for a Breeze-Entitytype, everything works fine:
breeze.EntityQuery.from("Employees").orderBy("EmployeeID");
As soon as I add a where-filter to the result
in the service-call, the whole IQueryable-Object seems to be casted to the base class Person
and not have a property EmployeeID
anymore:
IQueryable<Person> result = GetAllEmployees(); //returns IQueryable<Employee>
result = result.Where(o => myHashSet.Contains(o.Id));
This causes the following Error:
Microsoft.Data.OData.ODataException: The query specified in the URI is not valid. Could not find a property named 'EmployeeID' on type 'Person'.
Apparently the where
wrapps the IQueryable
into a new IQueryable
of the type of the variable it is stored in. The ElementType
of the original IQueryable is lost.
You can see this when you break at the where
and inspect result.ElementType
. As soon as you step over the where
it changes from Employee
to Person
.
With the following Code we restore the ElementType (feed it with result.ElementType
from before the where
):
public static IQueryable<T> ToTypedQueryable<T>(this IEnumerable<T> source, Type theType, bool exact = false) {
if (source == null) throw new ArgumentNullException("source");
System.Collections.IList result = (System.Collections.IList)typeof(List<>)
.MakeGenericType(theType)
.GetConstructor(Type.EmptyTypes)
.Invoke(null);
foreach (var s in source) {
Type t = s.GetType();
if (t == theType) {
result.Add(s);
} else if (!exact && t.IsSubclassOf(theType)) {
result.Add(s);
}
}
return (IQueryable<T>)(result.AsQueryable());
}