例如。有一个名为A的课程。
public class A
{
[Key]
[Required]
public virtual Guid Id {get;set;}
[Required]
public virtual string Name {get;set;}
[Required]
public virtual B B {get;set;}
}
当我调用此方法时,它将抛出B不能为空的异常。
public void Edit(Guid id, string name)
{
A a = _DbSet.Find(id);
a.Name = name;
_DbContext.SaveChanges();
}
但这会成功。
public void Edit(Guid id, string name)
{
A a = _DbSet.Find(id);
a.Name = name;
B b = a.B;
_DbContext.SaveChanges();
}
这是实体框架的错误吗?
我在版本6.1中使用它。
====================================
我发现一个常规的例子,如果属性链接到实体并且它没有从数据库加载,那么当你调用SaveChanges()
时它会抛出异常
答案 0 :(得分:0)
这不是一个错误 - 它是一个功能!您已将B
指定为Required
,但也指定virtual
,这意味着它将被延迟加载 - 换句话说,在您引用它之前,它不会被加载。
所以在你的第一个例子中,你永远不会加载B
,所以你得到了例外。在第二个示例中,您引用B
,这意味着对数据库的另一次调用,并且它被加载。
您需要致电Include
以急切加载B
。很遗憾,您无法将Include
与Find
一起使用,因此请尝试以下方式:
A a = _DbSet.Include("B").SingleOrDefault(a => a.id == id);
答案 1 :(得分:0)
我查看了Entity Framework的源代码。我发现bug的原因是关于Validate
类EF汇编的ValidationAttributeValidator
方法。
当一个实体要验证时调用此方法。它会检查Attribute
的任何Property
。但是,RequiredAttribute
不属于EF程序集。 GetValidationResult
的{{1}}方法不关心延迟加载EF。
所以,我认为解决方案是更改RequiredAttribute
类的Validate
方法的代码。如果ValidationAttributeValidator
为Attribute
,请忽略它,并使用延迟加载来验证属性。