使用内置 Linq to SQL 驱动程序在 LinqPad 中进行 运行 Entity Framework 核心查询的更简单方法?

Easier way to run Entity Framework Core queries in LinqPad with builtin Linq to SQL driver?

注:这是个老问题。对于 LinqPad 5,您有我在下面描述的限制,因为它不是用 .NET Core 编写的。但现在您可以使用较新的 LinqPad 6 or 7,它完全支持 Entity Framework 核心,包括用于多个数据库系统的驱动程序。


我想分析Entity Framework核心查询,我从现有代码复制到LinqPad中,比如

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

我知道,Linqpad 不支持 .NET Core, 所以我必须稍微调整一下 - 为此,我创建了一个扩展方法,如下所示:

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

需要重载的GetAll函数来获取类型——它只是创建一个空的新对象并将其传入,以便switch语句可以正确地推导出正确的类型和return正确的查询。

效果很好,但是 需要付出很多努力 才能将每种类型都放入 switch 语句中。

所以我的问题是:

如何以更智能的方式实现这一点,即不必指定每个实体类型?

LINQPad 的 UserQuery 对象似乎有一个方法正是您想要的:

public static class Ext {
    public static IEnumerable GetAll<T>(this UserQuery uq) =>uq.GetTable(typeof(T));
}

我相信您可以通过以下方式保持类型安全:

public static IQueryable<T> GetAll<T>(this UserQuery uq) => (IQueryable<T>)uq.GetTable(typeof(T));

使用您原来的 IEnumerable 版本会导致所有表被一个接一个地加载到内存中,然后在对象上执行 LINQ。使用 IQueryable<T> 将查询转换为 SQL - 在 LINQ to SQL 和 EF 的翻译不同(没有充分理由)的情况下,这可能是不可取的,但我可以看到问题EF 特定功能(例如 IncludeDbFunctions,尽管我写了空的 Include 扩展方法来隐藏一些)。

如果 IQueryable 版本不起作用,ITable<> 版本可能:

public static ITable<T> GetAll<T>(this UserQuery uq) where T : class => (ITable<T>)uq.GetTable(typeof(T));