使用内置 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<T>
将查询转换为 SQL - 在 LINQ to SQL 和 EF 的转换不同(没有充分理由)的情况下,这可能是不可取的,但我可以看到 EF 特定功能的问题(例如Include
和 @ 987654327@,虽然我写了空的Include
扩展方法来隐藏一些)。
如果IQueryable
版本不起作用,ITable<>
版本可能:
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 => pi.Id ...
,而非类型版本(你的答案中的第一个)工作正常
我终于找到了一种让它与输入结果一起工作的方法:public static IEnumerable<T> GetAll<T>(this UserQuery uq) => (IEnumerable<T>)uq.GetTable(typeof(T));
- 这工作正常,所以原因是接口类 IQueryable<T>
和 ITable<T>
不是 100% 兼容使用 Linq。
@Matt 我认为这是不对的——IQueryable<T>
是 LINQ(到 SQL/EF)的基础。如果您转换为IEnumerable<T>
,我会担心您将整个表拉入内存,而不是执行 SQL 查询,而是执行 LINQ to Objects,这可能会略有不同。以上是关于使用内置 Linq to SQL 驱动程序在 LinqPad 中运行 Entity Framework Core 查询的更简单方法?的主要内容,如果未能解决你的问题,请参考以下文章
LINQ to SQL 调用 SQL Server 的系统函数
使用 SQL Server Compact Edition 的 Linq-to-SQL