EF:一对多关系 - 查询数据子集

时间:2012-09-28 11:41:48

标签: entity-framework lazy-loading

我正在尝试从一对多关系中获取一组实体作为IQueryable,因此我可以在从数据库中获取数据之前过滤掉数据。

为清楚起见,请考虑以下示例:

我目前有一个实体“用户”,其中有一组图片:

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

图片实体可能属于也可能不属于用户,因此,其定义中没有用户属性。

用户可能有数千张图片,但我想选择前10个,例如,按Picture.Id排序。有没有办法做到这一点?

也许有些事情如下:

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

谢谢!

1 个答案:

答案 0 :(得分:4)

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

查询语法

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