c# - Entity Framework 6 : Skip() & Take() do not generate SQL, 相反,结果集在加载到内存后被过滤。还是我做错了什么?

标签 c# entity-framework-6 profiler

我有以下代码应该获取一些 book,并从那本书中检索前 2 个 tag(Tag 实体)( Book 实体)。 所以 TagsBook 实体的 navigation property

using (var context = new FakeEndavaBookLibraryEntities())
{
      Book firstBook = context.Set<Book>().Take(1).First();
      var firstTwoTags = firstBook.Tags.OrderBy(tag => tag.Id).Skip(0).Take(2).ToList();
}

期望获得必须由 EF 生成的以下 SQL 查询。

SELECT TOP(2)
       [Extent2].[Id]      AS [Id],
       [Extent2].[Version] AS [Version],
       [Extent2].[Name]    AS [Name]
FROM   [Literature].[BookTagRelation] AS [Extent1]
       INNER JOIN [Literature].[Tag] AS [Extent2]
         ON [Extent1].[TagId] = [Extent2].[Id]
WHERE  [Extent1].[BookId] = 1 /* @EntityKeyValue1 - [BookId] */

相反,EF Profiler 向我显示 EF 正在生成无限结果集(如SELECT * FROM ..。)

SELECT [Extent2].[Id]      AS [Id],
       [Extent2].[Version] AS [Version],
       [Extent2].[Name]    AS [Name]
FROM   [Literature].[BookTagRelation] AS [Extent1]
       INNER JOIN [Literature].[Tag] AS [Extent2]
         ON [Extent1].[TagId] = [Extent2].[Id]
WHERE  [Extent1].[BookId] = 1 /* @EntityKeyValue1 - [BookId] */

Here is a scheme fragment if you need it

我还尝试将 .AsQueryable() 附加到 firstBook.Tags 属性和/或删除 .Skip(0 ) 方法如下所示,但这也没有帮助

      var firstTwoTags = firstBook.Tags.AsQueryable().OrderBy(tag => tag.Id).Skip(0).Take(2).ToList();

同样的不良行为:

SELECT [Extent2].[Id]      AS [Id],
       [Extent2].[Version] AS [Version],
       [Extent2].[Name]    AS [Name]
FROM   [Literature].[BookTagRelation] AS [Extent1]
       INNER JOIN [Literature].[Tag] AS [Extent2]
         ON [Extent1].[TagId] = [Extent2].[Id]
WHERE  [Extent1].[BookId] = 1 /* @EntityKeyValue1 - [BookId] */

您在使用 Entity Framework 6 时遇到过同样的问题吗?

是否有任何变通方法来解决这个问题,或者我以错误的方式设计了查询...?

感谢任何提示!

最佳答案

firstBook.Tags是延迟加载的 IEnumerable<Tag> .在第一次访问时,所有标签都被加载,随后尝试将其变成 IQueryable<Tag>。不工作,因为你不是从你可以明智地查询的东西开始的。

相反,从已知商品开始 IQueryable<Tag> .类似的东西

Tag firstTag = context.Set<Tag>()
    .Where(tag => tag.Books.Contains(firstBook))
    .OrderBy(tag => tag.Id).Skip(0).Take(1).SingleOrDefault();

应该可以。您可能需要稍作调整才能将过滤条件变成 EF 可以理解的内容。

关于c# - Entity Framework 6 : Skip() & Take() do not generate SQL, 相反,结果集在加载到内存后被过滤。还是我做错了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44864909/

相关文章:

c# - 我如何理解 visual studio profiler 报告?

c# - WCF 用户名身份验证 - 教程中的异常

c# - 在 C# 中在服务器和客户端之间传递自定义复杂对象

c# - XUnit.net 在运行后立即捕获每个测试的结果

c# - 使用文件名从服务器 "programmatically"上的客户端上传文件或 "programmatically"将文件名分配给 UploadFile 控件

c# - Entity Framework linq 到 sql 转换问题

c# - Linq to 实体扩展方法内部查询 (EF6)

c# - 该属性必须是有效的实体类型,并且该属性应该具有非抽象 getter 和 setter。 Entity Framework

c++ - 如何在 Linux 上分析我的 C++ 应用程序

CUDA原子导致分支发散