I am using Dynamic Linq to perform some queries (sorry but it's my only option). As a result, I am getting an IQueryable
instead of an IQueryable<T>
. In my case, I want an IQueryable<Thing>
where Thing
is a concrete type.
My query is as such:
public IQueryable<Thing> Foo(MyContext db)
{
var rootQuery = db.People.Where(x => x.City != null && x.State != null);
var groupedQuery = rootQuery.GroupBy("new ( it.City, it.State )", "it", new []{"City", "State"});
var finalLogicalQuery = groupedQuery.Select("new ( Count() as TotalNumber, Key.City as City, Key.State as State )");
var executionDeferredResults = finalLogicalQuery.Take(10); // IQueryable
IQueryable<Thing> executionDeferredTypedThings = ??; // <--- Help here!!!!
return executionDeferredTypedThings;
}
My Thing.cs:
public class Thing
{
public int TotalNumber { get; set; }
public string City { get; set; }
public string State { get; set; }
}
Yes, I know the exact above thing can be done without Dynamic Linq but I have some variableness going on that I've simplified out of here. I can get it to work with my variableness if my return type is simply IQueryable
but I can't figure out how to convert to IQueryable<Thing>
while keeping it execution-deferred and while also keeping Entity Framework happy. I do have the dynamic Select
always returning something (with the correct data) that looks like a Thing
. But I simply can't figure how to return the IQueryable<Thing>
and could use some help there. Thanks!!
Failed Attempt 1
Based on Rex M's suggestion, I am now trying to use AutoMapper to solve this problem (although I am not committed to this approach and am willing to try other approaches). For the AutoMapper approach, I am doing it as such:
IQueryable<Thing> executionDeferredTypedThings = executionDeferredResults.ProjectTo<Thing>(); // <--- Help here!!!!
But this results in an InvalidOperationException:
Missing map from DynamicClass2 to Thing. Create using Mapper.CreateMap.
The thing is, while I have defined Thing
, I have not defined DynamicClass2
and as such, I cannot map it.
Failed Attempt 2
IQueryable<Thing> executionDeferredTypedThings = db.People.Provider.CreateQuery<Thing>(executionDeferredResults.Expression);
This gives an InvalidCastException and seems to be the same underlying problem that the above AutoMapper fail hits:
Unable to cast object of type 'System.Data.Entity.Infrastructure.DbQuery'1[DynamicClass2]' to type 'System.Linq.IQueryable'1[MyDtos.Thing]'.
.Take(10).Select(x => new Thing() { })
? Sorry, I haven't used it before. – Wiedmann.Take(10).Select(x => new Thing{City = Key.City ?? null))
, if that makes sense. I don't think that's really the right path to take for this because I'm doing conditional grouping. – EyotGroupBy
andSelect
strings dynamically from something else just to let Dynamic Linq do the plumbing part. But all that have an overhead, so I'm wondering if some strongly typed group/select helpers wouldn't do that better. – SymbiosisIQueryable<Thing>
or justIEnumerable<Thing>
that has deferred execution? The difference in this case between the two is thatIQueryable<Thing>
can be further modified (e.g. you can further filter the query) andIEnumerable<Thing>
can't. – Isidroisinglass