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;