【问题标题】:Entity Framework Code First update error with unloaded required navigation property实体框架代码首次更新错误,已卸载所需的导航属性
【发布时间】:2012-01-21 01:18:06
【问题描述】:

我发现,如果我根据需要设置导航属性(使用 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();
}

当我在地址属性上没有“必需”属性的情况下尝试此操作时,不会发生错误。使用Required 属性,我得到“地址字段是必需的!”。由于每个用户都应该有一个地址,我希望该属性创建一个一致的模型。

在一些论坛中,我发现一些帖子建议在加载父实体时包含导航属性(换句话说,急切加载),但如果我们有太多导航属性,这不是一种可行的方法。

我做错了什么还是有其他方法可以实现这种功能?

【问题讨论】:

标签: entity-framework ef-code-first


【解决方案1】:

在您的 User 类中定义 public int AddressId。它会在加载用户时加载。我认为这将解决问题。

更新: 好吧,我已经复制了你的问题。您有几个选项可以防止这种情况发生。但有一件事是肯定的。您必须从您的 Address 属性中删除 [Required] 属性。这是您的问题的根源(这是合理的,因为您告诉 EF “我想要地址 object (不是外键,而是导航属性)存在。如果它为空,则抛出异常")。
此外,在 User 类中定义 int 类型的 AddressId 属性。

请注意,您还可以在 Address 实体中定义 public virtual ICollection<User> Users { get; set; }

您可以通过将 [Required] 放在 AddressId 上或使用流利的 api 来告诉 EF 所需的属性:
在您的用户映射类中:
this.HasRequired(t => t.Address) 。与许多() .HasForeignKey(d => d.AddressId);

【讨论】:

  • 是错字还是您将 [Table("Address")] 错误地添加到用户类?
  • @CagatayKalan:更新了我的答案。
  • 如果根据需要设置AdressId,如何同时创建一个带有地址的用户记录?地址尚未在数据库中创建,因此它没有 ID。 id 将在标识字段分配新 id 时创建。那么当人的 AddressId 还不存在时如何设置呢?
  • 我尝试了您的建议,是的,流利的 api 可以根据需要设置关系,但这只会通过将外键设置为不可为空的字段来将所需的规则委托给数据库。但是,由于我必须从模型中删除 [Required] 属性,因此业务模型仍然无法确保所需的规则。这在 NHibernate 和 Hibernate 中更准确地实现了,所以从概念上讲我的问题还没有解决。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多