我有以下代码应该获取一些 book
,并从那本书中检索前 2 个 tag
(Tag
实体)( Book
实体)。
所以 Tags
是 Book
实体的 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/