以下代码:
using (var db = new Entities())
{
db.Blogs.First().Posts.Skip(10).Take(5).ToList();
}
将生成以下SQL:
-- statement #1
SELECT TOP ( 1 ) [c].[Id] AS [Id],
[c].[Title] AS [Title],
[c].[Subtitle] AS [Subtitle],
[c].[AllowsComments] AS [AllowsComments],
[c].[CreatedAt] AS [CreatedAt]
FROM [dbo].[Blogs] AS [c]
-- statement #2
SELECT [Extent1].[Id] AS [Id],
[Extent1].[Title] AS [Title],
[Extent1].[Text] AS [Text],
[Extent1].[PostedAt] AS [PostedAt],
[Extent1].[BlogId] AS [BlogId],
[Extent1].[UserId] AS [UserId]
FROM [dbo].[Posts] AS [Extent1]
WHERE [Extent1].[BlogId] = 1 /* @EntityKeyValue1 */
(来自http://ayende.com/blog/4351/nhibernate-vs-entity-framework-4-0)
NB Skip and Take尚未转换为SQL,导致博客中的所有帖子都从数据库加载,而不仅仅是我们要求的5个。
这似乎是危险的,可怕的低效率。令人难以置信的是,是什么给出了什么?
答案 0 :(得分:19)
发生这种情况的原因是调用First,这导致Blog
对象被实现。任何进一步的遍历都需要更多的查询。
请尝试使用db.Blogs.Take(1).SelectMany(b => b.Posts).Skip(10).Take(5).ToList();
在一个查询中执行此操作。您可能希望在.Take(1)
之前添加某种博客排序,以确保确定性结果。
修改强> 实际上你必须在Skip之前使用OrderBy(否则LINQ to Entities将抛出异常),这使它类似于:
db.Blogs.OrderBy(b => b.Id).Take(1) // Filter to a single blog (while remaining IQueryable)
.SelectMany(b => b.Posts) // Select the blog's posts
.OrderBy(p => p.PublishedDate).Skip(10).Take(5).ToList(); // Filter to the correct page of posts
答案 1 :(得分:2)
正如他在帖子中建议的那样,您可以使用EQL来执行此查询。类似的东西:
// Create a query that takes two parameters.
string queryString =
@"SELECT VALUE product FROM
AdventureWorksEntities.Products AS product
order by product.ListPrice SKIP @skip LIMIT @limit";
ObjectQuery<Product> productQuery =
new ObjectQuery<Product>(queryString, context);
// Add parameters to the collection.
productQuery.Parameters.Add(new ObjectParameter("skip", 3));
productQuery.Parameters.Add(new ObjectParameter("limit", 5));
// Iterate through the collection of Contact items.
foreach (Product result in productQuery)
Console.WriteLine("ID: {0}; Name: {1}",
result.ProductID, result.Name);
从此处获取的代码:http://msdn.microsoft.com/en-us/library/bb738702.aspx
答案 2 :(得分:1)
您可以尝试获取您的第一个博客并使用博客ID过滤此类帖子:
Blog blog = db.Blogs.First();
blog.posts = Posts.Where(r=>r.blogID=blog.id).Skip(10).Take(5).ToList();