调用SaveChanges时出现奇怪的DbEntityValidationException

时间:2013-08-12 15:07:33

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

我正忙着使用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();
}

异常消息:

enter image description here

但是:当我使用以下代码时,我没有异常,路径会成功保存到数据库。

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; }
}

2 个答案:

答案 0 :(得分:2)

根据您的实体定义,

public virtual DocumentType Type是必需的,但是在第一个示例中,如果未启用预先加载,则Type将为null(这是我的假设)。

第二个示例有效的原因是因为Type在此行var x = document.Type;上加载了延迟。您可以启用预先加载,也可以使用.Include()有选择地加载Type属性。

查看此链接,了解有关各种类型的EF加载相关实体的信息。

http://msdn.microsoft.com/en-us/data/jj574232.aspx

答案 1 :(得分:2)

我认为这个问题是因为Lazy Loading

事实上,通过调用此行:

Document document = _db.Documents.SingleOrDefault(x => x.ID == doc.ID);

您只获得Document实体的标量属性,其导航属性保持为null ...! (设置一个断点并查看)。

但是,当你拨打这一行时:

var x = document.Type;

您强制EF查询数据库以将Type导航属性提取到内存中并将其附加到dbcontext。确实这是一种正常行为,懒惰加载! - 除非真的需要,否则什么也得不到。

所以,如你所见,这当然不是一个奇怪的错误!这只是延迟加载的副作用......