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?

1 Answers

1
NetMage On Best Solutions

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));