延迟加载,集合以及单个或第一个

时间:2014-05-02 21:44:21

标签: c# entity-framework lazy-loading

我有以下型号:

用户拥有一组照片。在Photo模型中,有一个名为IsProfilePhoto的属性。

当我执行以下操作时,结果与预期不符。

var user = dbContext.Users.SingleOrDefault(u => u.Id == 1);
var profilePhoto = user.Photos.SingleOrDefault(p => p.IsProfilePhoto);

启用延迟加载后,会执行两次查询。

第一个按预期通过id获取用户。 然而,第二个按用户ID获取照片集合,然后在内存中进行IsProfilePhoto上的匹配。

我希望延迟加载它也会将SingleOrDefault添加到查询中。

这是不可能的,我必须总是反过来吗?例如。

var profilePhoto = dbContext.Photos.SingleOrDefault(p => p.UserId == 1 && p.IsProfilePhoto);
var user = profilePhoto.User;

我得到了推理,只有某些原因可以让用户更方便地获取个人资料照片。

4 个答案:

答案 0 :(得分:3)

您可以使用投影通过单个数据库查询获取结果:

var userWithProfilePhoto = dbContext.Users
    .Where(u => u.Id == 1)
    .Select(u => new
    {
        User = u,
        ProfilePhoto = u.Photos.Where(p => p.IsProfilePhoto).FirstOrDefault()
    })
    .SingleOrDefault();

userWithProfilePhoto.UseruserWithProfilePhoto.ProfilePhoto是您要查找的两个实体。

答案 1 :(得分:2)

您必须使用Eagerly加载来加载多个级别。延迟加载,在您访问它时加载级别。

var user = dbContext.Users.Include(u => u.Photos).SingleOrDefault(u => u.Id == 1);
var profilePhoto = user.Photos.SingleOrDefault(p => p.IsProfilePhoto);

答案 2 :(得分:1)

这是LINQ方法的细微差别。

您可以将过滤作为查询的一部分进行:

var profilePhoto = user.Photos.Where(p => p.IsProfilePhoto).SingleOrDefault();

由于LINQ to Entities中的这种行为,我尝试始终对WhereFirstSingle的条件和无参数重载使用FirstOrDefault方法, SingleOrDefaultAnyCount

编辑:

我的不好,MSDN直接提到它,但是对导航属性的任何引用(启用延迟加载时)都会加载所有相关记录。

我最好的建议是a)接受额外的数据库访问,或者b)在你的替代例子中进行查询,第一个表是“一对多”关系的“多个”。

答案 3 :(得分:0)

首先,FirstOrDefault是懒惰加载,Single和SingleOrDefault急切加载。如果在查询返回多个项目时不需要抛出异常,则可以将其更改为FirstOrDefault。