我发现,如果我根据需要设置导航属性(使用Required属性)并使用延迟加载代理,当我加载父实体并且除了尝试保存在同一上下文中什么也不做之外,会发生EntityValidationError这就像“需要xxx字段”。
使用Java中的hibernate和.NET中的NHibernate,可以只获取没有导航属性的实体(所有延迟加载),更新它并再次保存。该框架意识到导航引用没有任何改变,也不会抛出任何错误。
示例如下
[Table("Address")]
public class Address
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int AddressId { get; set; }
[Required, StringLength(512)]
public virtual string AddressLine1 { get; set; }
}
[Table("User")]
public class User
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
[Required]
public string Name {get; set;}
[Required]
public virtual Address Address {get; set;}
}
void LoadAndSaveUser() {
var user = Context.Users.First();
user.Name = "foo";
// if i comment out this line
// ( probably EF fetches the lazy loaded entiy )
// the code works. it is strange though because i don't access any property/method of the Address
// var dummy = user.Address
Context.SaveChanges();
}
当我在Address属性上没有“Required”属性的情况下尝试此操作时,不会发生错误。使用Required属性,我得到“Address field is required!”。由于每个用户都应该有一个地址,我希望该属性创建一致的模型。
在某些论坛中,我发现帖子建议在加载父实体时包含导航属性(换句话说是急切加载),但如果我们有太多导航属性,那么这不是一种可行的方法。
我做错了什么或有没有其他方法来实现这样的功能?
答案 0 :(得分:1)
在public int AddressId
课程中定义User
。它会在加载用户时加载。我认为这样可以解决问题。
<强>更新强>:
好吧,我已经复制了你的问题。你有几个选择来防止这种情况发生。但有一件事是肯定的。您必须从Address
媒体资源中删除[必填] 属性。这是你的问题的根源(这是合理的,因为你告诉EF“我想要地址对象(不是外键而是导航属性)。如果它是null,则抛出异常“)。
另外,在AddressId
类中定义int
类型的User
属性。
请注意,您还可以在public virtual ICollection<User> Users { get; set; }
实体中定义Address
。
您可以通过将[Required]
放在AddressId
上或使用流畅的api告诉EF有关所需属性的信息:
在您的用户映射类中:
this.HasRequired(t =&gt; t.Address)
。和很多()
.HasForeignKey(d =&gt; d.AddressId);