Reputation: 27016
Note: This is an old question. With LinqPad 5 you had the limitations I've described below, because it isn't written in .NET Core. But now you can use the newer LinqPad 6 or 7, which fully supports Entity Framework Core including drivers for multiple database systems.
I want to analyze Entity Framework Core queries, which I copied from existing code into LinqPad like
UserQuery this_context;
void Main()
{
this_context = this;
var validationResult = (
from ProjectInfo pi in this_context.GetAll<ProjectInfo>()
join GeneralInformation gi in this_context.GetAll<GeneralInformation>()
on pi.Id equals gi.Id into gpi
from gps in gpi.DefaultIfEmpty()
select new { ... }).ToList();
}
I know, that Linqpad does not support .NET Core, so I have to tweak it a bit - for this purpose I have created an Extension method as follows:
public static class Ext
{
public static IEnumerable GetAll<T>(this UserQuery uq)
where T: new()
{
return GetAll(uq, new T());
}
private static IEnumerable GetAll<T>(this UserQuery uq, T a)
{
switch (a)
{
case ProjectInfo v:
return uq.ProjectInfo.Select(s => s);
case GeneralInformation v:
return uq.GeneralInformation.Select(s => s);
// ... many more cases like the above
default: // unknown type
throw new TypeAccessException($"Unsupported type {a.GetType().FullName}");
}
}
}
The overloaded GetAll
function is required to get the type - it just creates an empty new object and passes it in so that the switch statement can properly deduct the correct type and return the right query.
That works fine, but it is a lot of effort to put in every single type into the switch statement.
So my question is:
How can this be achieved in a smarter way, i.e. without having to specify every single entity type?
Upvotes: 0
Views: 823
Reputation: 26926
LINQPad's UserQuery
object seems to have a method that is exactly what you want:
public static class Ext {
public static IEnumerable GetAll<T>(this UserQuery uq) =>uq.GetTable(typeof(T));
}
I believe you could stay type safe with:
public static IQueryable<T> GetAll<T>(this UserQuery uq) => (IQueryable<T>)uq.GetTable(typeof(T));
Using your original IEnumerable
version causes all the tables to be loaded into memory one by one and then the LINQ executed on the objects. Using IQueryable<T>
translates the query to SQL - this may not be desirable in the cases where LINQ to SQL and EF differ in translation (for no good reason), but I could see issues with EF specific capabilities (e.g. Include
and DbFunctions
, though I have written empty Include
extension methods to hide that some).
If the IQueryable
version doesn't work, an ITable<>
version may:
public static ITable<T> GetAll<T>(this UserQuery uq) where T : class => (ITable<T>)uq.GetTable(typeof(T));
Upvotes: 1