我怎样才能拥有1:多表但只有1:1的导航属性?

时间:2012-10-12 16:39:14

标签: .net entity-framework ef-code-first entity-framework-5

我有两个实体;让我们称他们为人和地址。一个人只有一个当前地址[在这里插入关于政治候选人的笑话],但也有以前的地址,这些地址也存储在地址表中。因此,我希望我的数据库表具有1:多的关系。

然而,在我的实体类中,我不希望Person和Address之间存在1:多的关系,因为我只对他们的当前地址感兴趣。 (如果我想了解他们以前的地址,那么我可以直接查看地址表)。所以,我想要Person对象上的1:多“Addresses”属性。相反,我想要一个1:1的Address属性,我将其设置为当前地址。

可以这样做吗?

2 个答案:

答案 0 :(得分:2)

通过映射无法做到这一点,因为EF关系紧跟在DB关系之后。此外,EF中的一对一关系基于将外键放在从属表中的主键上(地址和人员需要具有完全相同的主键值),并且此要求不适用于您希望在表也​​是。

我会尝试这种方法(未经测试):

public class MyContext : DbContext {

    public MyContext() {
        ((IObjectContextAdapter)this).ObjectContext.ObjectMaterialized += 
            (sender, e) => {
                var person = e.Person as Person;
                if (person != null) {
                    // Fill the property manually
                    person.Address = this.Addresses.FirstOrDefault(/* some condition */);
                }
    }

    protected override void OnModelCreating(DbModelBuilder builder) {
        // Do not map the propery
        builder.Entity<Person>().Ignore(p => p.Address);

        // other mapping
    }

    public override int SaveChanges() {

        // TODO: here you must have your own change tracking logic
        // for address to know when the address has changed and 
        // new record must be created in the database for old address

        return base.SaveChanges();
    }

    // rest of context class
}

答案 1 :(得分:0)

不,它无法完成。导航属性表示外键关系,数据库中的FK关系表示一个人的许多地址。例如,当前地址是数据库中特定查询的结果 - 取决于“当前”定义的方式 - “select top(1)... order by addresscreationdate descending”查询所有某人的地址。

我认为可能的解决方案是:

  • 使用人员表中的外键CurrentAddressId创建第二个关系,引用当前地址。然后,您的CurrentAddress课程中可以有导航参考Person
  • 或执行查询以使用GetCurrentAddress(Person person)方法或类似方法在存储库或服务类中加载当前地址。但是,您不能在Person类的当前地址上拥有导航属性。