我是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。这会导致问题吗? (同样,不是我的数据库 - 它是第三方。)非常感谢任何帮助。谢谢!
答案 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在我需要时将我的地址信息从人员身上获取,这一切都有效。谢谢大家的帮助!