实体框架延迟加载不正确的行为

时间:2013-07-15 14:03:21

标签: c# asp.net-mvc entity-framework entity-framework-5 lazy-loading

在我的控制器操作中,我正在尝试将新图像添加到数据库中。图像需要与设备相关联,该设备与用户相关联。

所以我有我的实体classess:

public class Image
{
   public int Id { get; set; }
   public string Url { get; set; }

   [Required]
   public virtual Device { get; set; }
}

public class Device
{
   public int Id { get; set; }
   public string Name { get; set; }

   [Required]
   public virtual User { get; set; }
}

public class User
{
   public int Id { get; set; }
   public string Login{ get; set; }
   public virtual ICollection<Device> Devices { get; set; }

   [Required]
   [DataType(DataType.EmailAddress)]
   public virtual string Email{ get; set; }
}

现在,当我尝试添加这样的新图像时:

var image = new Image(); 
image.Device = Db.DbSet<Device>().Find(1); 
Db.DbSet<Image>().Add(image); 
Db.DbSet<Image>().SaveChanges();

当我使用这个Find来提供现有设备(用户和所有属性设置正确)时,我没有在设备中获得正确填充的用户属性。这就像延迟加载不起作用。有一个User对象的实例,但它的id设置为0,并且所有其他字段都设置为默认值。

我将所有导航属性设置为虚拟,并且延迟加载在我的其他实体上工作正常,因此它绝对不会被关闭或者其他东西。

有趣的是,当我在添加图像之前更改我的代码和比较之后,它会加载用户并正常工作:

if (AuthenticationHelper.CurrentUser != image.Device.User)
    return null;

正好像它在这一刻设法加载用户。如果我们更改此比较订单,则关注image.Device.User != AuthenticationHelper.CurrentUser,它将不再有效。

有什么想法吗?

3 个答案:

答案 0 :(得分:2)

我认为延迟加载工作正常。您找到ID为1的Device,然后将其分配给图片而不访问User上的Device属性。如果UserID模型上没有显式的外键Device属性,则永远不会访问User属性,因此永远不会有值,并插入null。

尝试将UserID(或User_ID(如果您想与实体框架的约定保持一致)添加到Device模型中,并且您的代码应该有效。

答案 1 :(得分:1)

问题可能是由实体默认构造函数中的实例化引用导航属性(Device.User)引起的。加载和保存实体时会导致副作用和意外行为。其他示例包括herehere

答案 2 :(得分:-1)

实体框架与LINQ to SQL或NHibernate在“延迟加载”方面并不完全相同。在EF中,设计决策是确保开发人员确切地知道他们何时访问资源,例如数据库。因此,Lazy Loading不会启用“自动”数据库重新查询;相反,它提供了资源的“延迟”加载。如果没有开发人员知道,EF将永远不会在稍后启动辅助数据库调用;相反,开发人员应该对.Load()方法进行显式调用以启动辅助调用,或者通过.Include()急切加载延迟资源。