首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >实体框架-代码优先:使用相同类型的多个子/可选属性进行映射

实体框架-代码优先:使用相同类型的多个子/可选属性进行映射
EN

Stack Overflow用户
提问于 2011-12-21 18:28:13
回答 1查看 1.1K关注 0票数 0

我的域模型有User和Address类

代码语言:javascript
运行
复制
public User
{
   int Id
   Address PrimaryAddress
   Address SecondaryAddress
   and some other Properties
}

两者都是可选的,但每个地址都必须有一个用户。Codeirst映射看起来像

代码语言:javascript
运行
复制
modelBuilder.Entity<User>()
   .HasOptional(u => u.PrimaryAddress)
   .WithRequired()
   .WillCascadeOnDelete(false);
modelBuilder.Entity<User>()
   .HasOptional(u => u.SecondaryAddress)
   .WithRequired()
   .WillCascadeOnDelete(false);

但这并没有产生预期的结果。我希望用户表有两列(int,null)指向地址表。地址表可能具有UserId (外键,整型,非空值)列。但是使用上面的代码,地址的"ID“列充当PK和FK (指向用户表)。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-12-21 21:15:17

您已经映射了一对一的关系,这正是您在数据库中看到的。简而言之,你想要实现的目标不可能通过这种方式实现。

特别是Address必须有一个User的部分无法工作,因为你在User实体上有两个导航属性,这将导致在Address表中有两个不同的FK列,它们必须为空,否则每个地址对于某些用户来说都必须是主要和次要的。

正确的模型使用默认映射进行映射(不需要流畅映射),因为它创建了具有两个FK的用户。address与user是两个一对多的关系,因为在理论上确实可以有多个用户使用相同的地址。

另一种选择是将关系建模为多对多,其中连接表将建模为具有附加属性AddressType的实体。

如果你真的想要遵循你当前的模型,你必须使用这个:

代码语言:javascript
运行
复制
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中被视为有效值,因此如果您对可为空的列具有唯一约束,则只有一条记录可以具有空值。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8588356

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档