我的域名模型包含用户和地址类
public User
{
int Id
Address PrimaryAddress
Address SecondaryAddress
and some other Properties
}
两者都是可选的,但每个地址都必须有一个用户。 Codeirst Mapping看起来像
modelBuilder.Entity<User>()
.HasOptional(u => u.PrimaryAddress)
.WithRequired()
.WillCascadeOnDelete(false);
modelBuilder.Entity<User>()
.HasOptional(u => u.SecondaryAddress)
.WithRequired()
.WillCascadeOnDelete(false);
但这并没有产生预期的结果。我期待用户表指向地址表的两个(int,null)列。和Address表可能有一个UserId(外键,int,非null)列。 但是使用上面的代码地址的“ID”列充当PK和FK(指向用户表)。
答案 0 :(得分:1)
您已映射一对一关系,这正是您在数据库中看到的内容。总之,你想要达到的目标是不可能的。
尤其是Address
必须具有User
的部分无法正常工作,因为User
实体上有两个导航属性,这将导致Address
表中的两个不同的FK列并且它们必须是可以为空的,否则每个地址都必须是某些用户的主要和次要地址。
使用默认映射映射正确模型(不需要流畅映射),因为它创建了具有两个FK来解决的用户。地址与用户有两对一的关系,因为理论上你可以让多个用户拥有相同的地址。
另一个选择是将关系建模为多对多关系,其中联结表将被建模为具有附加属性AddressType
的实体。
如果你真的想要关注你当前的模型,你必须使用它:
modelBuilder.Entity<User>()
.HasOptional(u => u.PrimaryAddress)
.WithOptionalPrincipal()
.WillCascadeOnDelete(false);
modelBuilder.Entity<User>()
.HasOptional(u => u.SecondaryAddress)
.WithOptionalPrincipal()
.WillCascadeOnDelete(false);
它将在Address
表中创建两个额外的FK列,并且关系本身将是一对多(一个用户可以有多个地址)。原因是强制执行一对一需要FK的唯一性,当前的EF版本不支持唯一密钥。您可以在后期处理中添加唯一约束FK列(通过custom DB initializer或EntityFramework.Migrations),但这会导致其他问题。 SQL中的空值被视为有效值,因此如果您对可空列具有唯一约束,则只有单个记录可以具有空值。