我正忙着使用MVC4开发ASP.net Web应用程序,并在尝试保存对db的一些更改时遇到了这个奇怪的错误。这段代码在我的一个控制器中。调用_db.Save()时,下面的代码会导致DbEntityValidationException,而后者又调用SaveChanges()。我正在使用EntityFramework V5。
Document document = _db.Documents.SingleOrDefault(x => x.ID == doc.ID);
if (document != null)
{
document.Location = idPath;
_db.Save();
}
异常消息:
但是:当我使用以下代码时,我没有异常,路径会成功保存到数据库。
Document document = _db.Documents.FirstOrDefault(x => x.ID == doc.ID);
if (document != null)
{
// Needed for SaveChanges to work
var x = document.Type;
document.Location = idPath;
_db.Save();
}
为什么会这样?是因为我的Documents集合属于List类型吗?请注意,我发现错误是由Type属性引起的。
以下是我的Document类的结构:
[Table("Document")]
public class Document
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public virtual int ID { get; set; }
[Required]
public virtual string Name { get; set; }
public virtual string Location { get; set; }
[Required]
public virtual DocumentType Type { get; set; }
[NotMapped]
public virtual HttpPostedFileBase File{ get; set; }
}
答案 0 :(得分:2)
public virtual DocumentType Type
是必需的,但是在第一个示例中,如果未启用预先加载,则Type
将为null(这是我的假设)。
第二个示例有效的原因是因为Type
在此行var x = document.Type;
上加载了延迟。您可以启用预先加载,也可以使用.Include()
有选择地加载Type
属性。
查看此链接,了解有关各种类型的EF加载相关实体的信息。
答案 1 :(得分:2)
我认为这个问题是因为Lazy Loading
。
事实上,通过调用此行:
Document document = _db.Documents.SingleOrDefault(x => x.ID == doc.ID);
您只获得Document
实体的标量属性,其导航属性保持为null ...! (设置一个断点并查看)。
但是,当你拨打这一行时:
var x = document.Type;
您强制EF查询数据库以将Type
导航属性提取到内存中并将其附加到dbcontext。确实这是一种正常行为,懒惰加载! - 除非真的需要,否则什么也得不到。
所以,如你所见,这当然不是一个奇怪的错误!这只是延迟加载的副作用......