2012-09-28 37 views
1

我试图从一个一对多的关系,一个IQueryable获取实体的集合,所以我可以从获取此之前筛选数据向下数据库。EF:一个一对多的关系 - 查询数据的一个子集

要清楚,请看下面的例子:

我现在有一个实体的“用户”,这有照片的集合:

public virtual ICollection<Picture> Pictures{ get; set; } 

图片实体可能会或可能不属于用户,因此,它的定义中没有User属性。

用户可能有数以千计的照片,但我想选择第10例如由Picture.Id订购。有没有办法做到这一点?

也许大意是这样的:

IQueryable<ICollection<Picture>> pictures = context.Users.Where(u=>u.UserId == userId).Select(c => c.Pictures) 

谢谢!

回答

4

基本思路是在用户的Pictures集合上使用OrderByTake方法。但是,由于您要确保只执行一个EntityFramework SQL查询而不加载用户的整个集合,因此需要以更具体的方式表示。

查询语法

var result = (from u in users 
       where u.Id == userId 
       from p in u.Pictures 
       orderby p.Id 
       select p).Take(10); 

方法的语法

var result = context.Users 
    .Where(u => u.Id == 2) 
    .SelectMany(u => u.Pictures) 
    .OrderBy(p => p.Id) 
    .Take(10); 

注意调用SelectMany。这一点很重要。基本上,这将所有选定用户的所有Pictures集合合并到一个列表中,并在这个扁平化元列表上继续查询。理论上这听起来像是一个很大的操作,但在这种情况下,应该只有一个具有特定ID的用户,所以它只是继续选择用户的Pictures集合。生成的SQL是一个单一的,快速的查询:

所得SQL查询(对于上述两个)

SELECT TOP (10) 
[Extent1].[User_Id] AS [User_Id], 
[Extent1].[Id] AS [Id], 
[Extent1].[Name] AS [Name] 
FROM [dbo].[Pictures] AS [Extent1] 
WHERE ([Extent1].[User_Id] IS NOT NULL) AND (2 = [Extent1].[User_Id]) 
ORDER BY [Extent1].[Id] ASC 
+0

这将是密集的数据?如在,这将获取所有数千张照片,然后订购并拿走我想要的?或者它会很懒,只选择我要求的那些,例如,前10张图片 – Karan

+0

LINQ尽可能地很懒。如果这是CLR对象或SQL数据库的集合 - 是的,这很懒!如果不是,LINQ2SQL将毫无用处。 :)实际上,这个LINQ表达式不会被评估,直到你强迫它变成这样 - 要么用'.ToList()'标记它,要么通过迭代器块访问它。 –

+0

那么如果我使用第一行,它会评估所有的图片? (10)不是惰性的,而第二块代码(在LINQ下是()懒惰?) – Karan

相关问题