我有2个类(用户和设备),定义如下。
public class User {
public int UserId { get; set; }
public virtual ICollection<Device> Devices { get; set; }
...
}
public class Device {
public int UserId;
public virtual User User { get; set; }
...
}
我为这两个实体中的每一个都有一个存储库,并且我已经在我的数据上下文中禁用了延迟加载。
public class MyDbContext : DbContext
{
public MyDbContext()
: base(name=MyDbContext)
{
this.Configuration.LazyLoadingEnabled = false;
}
}
我正在尝试检索与用户帐户相关联的所有设备。
我尝试过两种不同的方式。
方法#1 - 在用户相关属性上调用负载
using (MyDbContext dbContext = new MyDbContext())
{
// performing some database operations ...
var user = dbContext.Users.Find(8);
// do some operations
if (user.Devices == null or user.Devices.Count() ==0)
dbContext.Entry(user).Collection(u => u.Devices).Load();
var devices = user.Devices;
}
方法#2 - 使用where
从设备集中检索using (MyDbContext dbContext = new MyDbContext())
{
// performing some database operations ...
var user = dbContext.Users.Find(8);
// do some operations
if (user.Devices == null or user.Devices.Count() ==0)
var devices = dbContext.Devices.Where(d => d.UserId == user.UserId).ToList();
}
由于某种原因,方法#1并不总是检索所有设备,但方法#2检索所有设备!有人可以解释一下我做错了吗?
我启动了SQL Server Profiler,看看我是否做错了什么。两种方法生成的查询都是相同的。所以我真的很困惑我做错了什么!
答案 0 :(得分:4)
有人可以解释一下我做错了吗?
我无法解释为什么您遇到了您遇到的问题,但我个人不使用Find()
或Load()
,因为这些方法在处理本地环境方面很复杂缓存。所以我建议以下查询:
var user = dbContext.Users
.Include(u => u.Devices);
.FirstOrDefault(u => u.id = 8);
由于您只检索单个用户,因此没有Cartesian个问题。此查询将在单个语句中使用用户和与该用户关联的所有设备填充上下文。
如果之后确实需要一个单独的变量与所有设备:
var devices = user.Devices;
关于我的答案的重要注释是因为我通常在Web环境中处理Entity Framework,我的代码不断创建/处理上下文,因此Entity Framework上的本地缓存几乎无用。对于非无状态应用程序(Winforms / WPF),这可能不是最佳解决方案。
根据您的评论更新
以后还有其他加载方法吗?
如Brendan Green's Comment所述,您可以使用:
var devices = dbContext.Devices
.Where(w => w.UserId == 8);
(请注意,这不会对数据源执行查询。)