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

Posted

技术标签:

【中文标题】使用内置 Linq to SQL 驱动程序在 LinqPad 中运行 Entity Framework Core 查询的更简单方法?【英文标题】:Easier way to run Entity Framework Core queries in LinqPad with builtin Linq to SQL driver? 【发布时间】:2019-04-18 13:10:33 【问题描述】:

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


我想分析 Entity Framework Core 查询, 我从现有代码复制到 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 语句可以正确推断出正确的类型并返回正确的查询。

这很好用,但是将每个类型都放入 switch 语句中需要付出很多努力

所以我的问题是:

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

【问题讨论】:

【参考方案1】:

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&lt;T&gt; 将查询转换为 SQL - 在 LINQ to SQL 和 EF 的转换不同(没有充分理由)的情况下,这可能是不可取的,但我可以看到 EF 特定功能的问题(例如Include 和 @ 987654327@,虽然我写了空的Include 扩展方法来隐藏一些)。

如果IQueryable 版本不起作用,ITable&lt;&gt; 版本可能:

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

【讨论】:

工作正常,这正是我想要的。非常感谢!然而,类型安全版本会因未知原因抛出 InvalidOperationException。 GetTable 之后可能需要.AsQueryable()?当我使用与 MS SQL 的连接对其进行测试时,我没有收到错误消息。我添加了另一个可能更好的类型安全版本。 在我的情况下,两种类型的版本都抛出InvalidOperationException: Could not translate expression 'Table(ProjectInfo).Cast().GroupJoin(Table(GeneralInformation).Cast(), pi =&gt; pi.Id ...,而非类型版本(你的答案中的第一个)工作正常 我终于找到了一种让它与输入结果一起工作的方法:public static IEnumerable&lt;T&gt; GetAll&lt;T&gt;(this UserQuery uq) =&gt; (IEnumerable&lt;T&gt;)uq.GetTable(typeof(T)); - 这工作正常,所以原因是接口类 IQueryable&lt;T&gt;ITable&lt;T&gt; 不是 100% 兼容使用 Linq。 @Matt 我认为这是不对的——IQueryable&lt;T&gt; 是 LINQ(到 SQL/EF)的基础。如果您转换为IEnumerable&lt;T&gt;,我会担心您将整个表拉入内存,而不是执行 SQL 查询,而是执行 LINQ to Objects,这可能会略有不同。

以上是关于使用内置 Linq to SQL 驱动程序在 LinqPad 中运行 Entity Framework Core 查询的更简单方法?的主要内容,如果未能解决你的问题,请参考以下文章

学习Linq To Sql

Linq to SQL(视图或表)?

LINQ to SQL 调用 SQL Server 的系统函数

使用 SQL Server Compact Edition 的 Linq-to-SQL

SQL Compact 不适用于 Linq to Sql,我应该使用啥?

在数据访问应用程序块之上使用“LINQ to SQL”和“WCF 数据服务”