使用EF Code First映射单向关系

时间:2012-08-03 01:55:09

标签: c# entity-framework ef-code-first

我是EF Code First的新手,这可能(希望!)是一个简单的问题。

我和人和地址之间有一个简单的关系:

People
------
PersonID
Name

Address
-------
AddressID
Address1
PersonID

大多数时候我的人员表中都有AddressID;但是这个db有点“向后”,因为它引用了PersonID。在我的代码中,我处理Person对象并希望得到它们的相关地址。这种关系可能是1个人有很多地址,但总是1:1。 (这是第三方数据库 - 我无法控制架构。)

如何在Code First中建立关系以关联Person和Address?我正在使用流畅的API,但我没有看到在没有两个实体的密钥的情况下进行设置的方法。理想情况下,我希望我的实体设置如下:

Person { 
 public int PersonID {get;set;}
 public string Name {get;set;}
 //other person properites

 //navigation property
 public Address Address {get;set;}
}

Address {
 public string Address1 {get;set;}
 //other properties for address

 //navigation property
 public Person Person {get;set;}
}

我已经尝试了几种方法来配置关系,但它不断出错。我已经尝试将Address类定义为复杂类型,但由于它是一个单独的表,这可以吗?此外,我已尝试使用HasOptional和WithOptionalDependant,但无济于事。

所以关于如何最好地配置我的EF CF逻辑以允许Address成为Person中的实体的任何想法。

非常感谢任何建议或帮助。

更新 我在下面尝试了Mark的建议,但是我得到了一个不同的错误。 (见我的评论)

我的地址实体设置将PersonID设置为实体键:

modelBuilder.Entity<Address>()
 .HasKey(a => a.PersonID);

modelBuilder.Entity<Address>()
 .Property(a => a.PersonID)
 .HasColumnName(<my real column name>);

因此,DB中的实体密钥是PersonID,但它也是FK返回Person。这会导致问题吗? (同样,不是我的数据库 - 它是第三方。)非常感谢任何帮助。谢谢!

2 个答案:

答案 0 :(得分:1)

你确定你想要1:1的关系吗?

  

关系可能是1个人有很多地址,但确实如此   总是1:1。 (这是第三方数据库 - 我无法控制架构。)

这意味着您实际上想要1:多关系正确吗?

话虽这么说,我认为导航集合是将地址映射到Person对象的理想方式:

Person { 
 public int PersonID {get;set;}
 public string Name {get;set;}
 //other person properites

 //navigation property
 public virtual ICollection<Address> Addresses {get;set;}
}

这里是相应的Fluent(假设您有一个PersonID映射到地址,您在描述数据库时会这样做,但不会在您的代码中执行)

modelBuilder.Entity<Person>()
            .HasMany(p => p.Addresses)
            .WithRequired(a => a.Person)
            .HasForeignKey(a => a.PersonID);

答案 1 :(得分:0)

我认为它不符合马克的建议。

modelBuilder.Entity<Person>()
  .HasOptional<Address>(p => p.Address)
  .WithRequired(a => a.Person);

我需要设置一个可选的:必需的映射,因为Person可能没有地址(不太可能,但我想这是可能的),但是地址有一个Person,因为地址PK是PersonID。

在序列化结果时,需要注意的是Person和Address之间的循环引用(我在将结果序列化为JSON时在控制器中捕获了它)。我通过在我的特定查询(我)获取人员地址信息的上下文中禁用代理创建来解决这个问题:

_context.Configuration.ProxyCreationEnabled = false;

一旦我这样做,我就会使用Lazy Loading在我需要时将我的地址信息从人员身上获取,这一切都有效。谢谢大家的帮助!