C# 实体框架延迟加载错误行为

C# 实体框架延迟加载错误行为,c#,asp.net-mvc,entity-framework,entity-framework-5,lazy-loading,C#,Asp.net Mvc,Entity Framework,Entity Framework 5,Lazy Loading,在我的控制器操作中,我试图向数据库添加新映像。图像需要与设备关联,而设备与用户关联 所以我有我的实体类: 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 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; }
}
就像它在这一刻设法加载用户一样。如果我们将此比较顺序更改为以下
image.Device.User!=AuthenticationHelper.CurrentUser
它不再工作


你知道这是怎么回事吗?

我认为延迟加载工作正常。您正在查找ID为1的
设备
,然后将其分配给图像,而无需访问
设备
上的
用户
属性。如果您的
设备
型号上没有明确的外键
UserID
属性,则永远不会访问
用户
属性,因此永远不会有值,并插入null


尝试将
UserID
(或
User\u ID
,如果您想遵守实体框架的约定)添加到
设备
模型中,您的代码应该可以工作。

实体框架在“延迟加载”方面与LINQ to SQL或NHibernate不太一样。在EF中,设计决策是确保开发人员准确地知道他们何时访问资源,例如数据库。因此,延迟加载不会启用“自动”数据库重新查询;相反,它提供了资源的“延迟”加载。EF将永远不会在开发人员不知道的情况下在以后启动辅助数据库调用;相反,开发人员应该显式调用
.Load()
方法来启动二次调用,或者通过
.Include()

急切地加载延迟的资源。这个问题可能是由于在实体默认构造函数中实例化了引用导航属性(
Device.User
)引起的。加载和保存实体时会产生副作用和意外行为。其他示例包括和。

您的
设备
类是否具有实例化
用户
属性的默认构造函数?如果是,请尝试在没有实例化的情况下它是否正常工作。@Slauma-结果证明您是对的!请添加一个答案,以便我可以接受。好的,它不加载
用户
,这可能是一种正确的行为,但是如果它知道这是一个db代理,并且它是从db获取的,那么它也应该避免验证此属性。即使它尝试验证-为什么不在此时加载它,当validatior访问
用户
时?我也只是尝试在
添加
方法之前调用
image.Device.User.Email.ToString()
,但它仍然不加载它-它只是抛出Null Ref异常,因为电子邮件仍然为空…@ukaszW.pl我会问一个愚蠢的问题,数据库中是否有ID为1的设备?是的。不管怎样,结果证明斯劳玛是对的。这是由于实例化实体默认构造函数中的导航属性造成的。非true-
加载
包含
上下文时使用。ContextOptions.LazyLoadingEnabled
设置为false。否则,访问时应加载导航属性。
var image = new Image(); 
image.Device = Db.DbSet<Device>().Find(1); 
Db.DbSet<Image>().Add(image); 
Db.DbSet<Image>().SaveChanges();
if (AuthenticationHelper.CurrentUser != image.Device.User)
    return null;