我有以下型号:
用户拥有一组照片。在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;
我得到了推理,只有某些原因可以让用户更方便地获取个人资料照片。
答案 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.User
和userWithProfilePhoto.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中的这种行为,我尝试始终对Where
,First
,Single
的条件和无参数重载使用FirstOrDefault
方法, SingleOrDefault
,Any
和Count
。
编辑:
我的不好,MSDN直接提到它,但是对导航属性的任何引用(启用延迟加载时)都会加载所有相关记录。
我最好的建议是a)接受额外的数据库访问,或者b)在你的替代例子中进行查询,第一个表是“一对多”关系的“多个”。
答案 3 :(得分:0)
首先,FirstOrDefault是懒惰加载,Single和SingleOrDefault急切加载。如果在查询返回多个项目时不需要抛出异常,则可以将其更改为FirstOrDefault。