【问题标题】:Entity Framework Model First 1:0..1 RelationshipEntity Framework Model First 1:0..1 关系
【发布时间】:2013-10-28 01:03:19
【问题描述】:

我在 Visual Studio 2012 的 Entity Framework 5 模型设计器中创建了以下模型:

然后我从模型生成数据库,在我的数据库中生成了以下表格:

请帮助我理解为什么 Entity Framework 会为一对零或一关联生成一对多关系。


更新 #1

此外,如果我将关联从 1:0..1 更改为 1:1,如下所示:

然后不仅数据库中还没有一对一的关系,现在一对多的关系倒过来了,这对我来说似乎更奇怪:


更新 #2

针对神秘人的评论和回答,我期望在 SQL Server 中看到的结构是有效的 1:0..1 关系,如下所示:

此外,我可以使用以下 Code First 流畅映射完全按照预期工作:

public class UserMap : EntityTypeConfiguration<User>
{
    public UserMap()
    {
        ToTable("Users");

        HasKey(t => t.UserId);

        Property(t => t.UserId)
            .HasColumnName("UserId");

        Property(t => t.Name)
            .HasColumnName("Name")
            .IsRequired()
            .HasMaxLength(50);

        Property(t => t.EmailAddress)
            .HasColumnName("EmailAddress")
            .IsRequired()
            .HasMaxLength(254);

        Property(t => t.CreatedDateTime)
            .HasColumnName("CreatedDateTime");

        HasOptional(t => t.Subscription)
            .WithRequired(t => t.User);
    }
}

public class SubscriptionMap : EntityTypeConfiguration<Subscription>
{
    public SubscriptionMap()
    {
        ToTable("Subscriptions");

        HasKey(t => t.SubscriptionId);

        Property(t => t.SubscriptionId)
            .HasColumnName("SubscriptionId");

        Property(t => t.TypeValue)
            .HasColumnName("TypeValue");

        Property(t => t.CreatedDateTime)
            .HasColumnName("CreatedDateTime");

        Property(t => t.ExpiresDateTime)
            .HasColumnName("ExpiresDateTime");

        HasRequired(t => t.User)
            .WithOptional(t => t.Subscription);
    }
}

所以,我知道使用 Code First Entity Framework 可以实现这种行为。我的问题是为什么不能使用 Model First 方法来做到这一点。

这里发生了什么,为什么?

谢谢!

【问题讨论】:

  • 您希望数据模型看起来如何?
  • 请参阅我的更新 #2。我希望它看起来像 SQL Server 中的有效 1:0..1 关系。
  • 是的,做到了。谢谢!

标签: visual-studio-2012 ef-code-first entity-framework-5 sql-server-2012 ef-model-first


【解决方案1】:

SQL 无法定义真正的 1:1 或 1:0..1 数据模型,除非两个实体具有相同的主键。即便如此,你也不能有 1:1,因为你不能在单个语句中将记录插入多个表中,因此数据模型必须允许 1:0..1,因为存在中间状态一个记录将在没有另一个的情况下存在。

在 SQL 中执行此操作的唯一方法是完全按照 EF 在这里所做的操作,创建 1:*,然后施加约束以确保唯一性(例如唯一约束)。但是,EF 不支持约束(您必须手动创建它们),因此可能会插入多个记录并违反您的模型。

编辑:

既然您已经澄清说您是在谈论模型优先,并且您正在寻找共享主键,那么这就是您必须做的事情。

右键单击关联,并在订阅和用户之间创建一个引用约束。这将导致 EF 生成您正在寻找的 1:0..1 关系。

【讨论】:

  • 我更新了我的问题以说明确实可以使用共享主键创建 1:0..1 关系。但是,它们的密钥不需要具有相同的名称。使用我在更新中提供的新示例,可以在一个语句中向 Users 表添加一条记录,然后在下一条语句中向 Subscriptions 表添加一条记录(反之亦然),而不会违反任何约束。我还展示了如何在 EF Code First 中实现这一点。
  • @TimS - 请注意,在我的回答中,我特别说“除非两个实体具有相同的主键”。从您的问题来看,您似乎并没有试图共享一个共同的主键,这就是为什么我以我的方式表达它的原因。但是,我建议以不同方式命名这些键会造成混淆,并且违反 EF 命名约定。你当然可以像你所做的那样覆盖它们。由于您最初的问题没有提到共享主键,并且您有不同的名称,所以您的意思并不明显,如果我们人类无法弄清楚,您希望 EF 怎么做?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多