【问题标题】:Entity Framework 1 to 0 or 1 relationship configurationEntity Framework 1对0或1关系配置
【发布时间】:2018-03-21 14:49:59
【问题描述】:

我有这门课

public class Parent
{
  [Key]
  public int Id { get; set; }
  public string Name { get; set; }
  public virtual Child Child { get; set; }
}

还有一个子类

public class Child
{
  [Key]
  [ForeignKey]
  public int ParentId { get; set; }
  public string Name { get; set; }
  public virtual Parent Parent { get; set; }
}

这种关系是这样的,父母可以有 0 个或 1 个孩子。我检查了 SO 并找到了两个解决方案。

modelBuilder.Configurations.Add(new ParentChildMap());

// solution 1
class ParentChildMap : EntityTypeConfiguration<Child>
{
    public ParentChildMap()
    {
        HasRequired(t => t.Parent).
            WithRequiredDependent(t => t.Child);    
    }
}

// solution 2
class ParentChildMap : EntityTypeConfiguration<Child>
{
    public ParentChildMap()
    {
         HasOptional(c => c.Parent)
            .WithRequired(c => c.Child);
    }
}

问题是,它们都在工作!但问题是,我不确定哪一个是正确的。哪一个为我提供了一个父母只能有 0 或 1 个孩子的映射。然后,对方在说什么?

【问题讨论】:

  • 这看起来根本不对,实际上。为什么 Child 有对 Parent 的引用?它不应该需要它,除了 ParentId。不应该需要变量。通过查看代码,您似乎想要的是HasOptional(c =&gt; c.Child).WithRequired(c =&gt; c.Parent); 此外,Child 应该有自己的 Id 作为主键,而 ParentId 应该是外键。
  • 您不应该在 Child 类中将 ParentId 作为 [Key],您想在 Child 类和 ParentId 属性上创建另一个 Id 属性请改用[ForeignKey] 属性。至于你的EntityTypeConfiguration&lt;Child&gt; 你想要HasRequired(t =&gt; t.Parent)
  • 我不确定哪个是正确的 -- 方法名称(包含“可选”、“必填”)应该会给你一个强烈的提示。两种解决方案都不正确。
  • omg 谢谢使用 ParentChild 而不是 DMATRFPR 和 DMATRFPR_FUPAFPLS 或者像这个主题的所有其他示例一样的废话。跨度>

标签: c# entity-framework


【解决方案1】:

让相关实体连同它们的基数一起添加到所需的关系中:

父母 1 0..1 孩子

你可以这样读:

(1) --> 0..1 Child 表示每个Parent可以有0个或1个Child,或者换句话说,Parent实体的Child属性是可选

(2) Parent 1 表示每个Child总是有1个Parent,或者换句话说,Child实体的Parent属性是必需的强>。

Child端对应上面的流畅配置是:

HasRequired(c => c.Parent).WithOptional(p => p.Child);

或者来自Parent 方面:

HasOptional(p => p.Child).WithRequired(c => c.Parent);

这两个是正确的并且完全等效 - 您可以使用一个或另一个,具体取决于您是从 Child(如您的示例中)还是从 Parent 开始配置。为避免出现差异,切勿两者都做。

为什么你当前的解决方案都不正确?

因为:

(解决方案1)

HasRequired(t => t.Parent).WithRequiredDependent(t => t.Child);

表示Parent 1 1 Child关系(父母必须始终有1个孩子)。

(解决方案 2)

HasOptional(c => c.Parent).WithRequired(c => c.Child);

表示Parent 0..1 1 Child关系(child可以有0个或1个parent,parent必须总是有1个child),即与你想要的相反。 p>

【讨论】:

  • 如果它的外键属性不遵循 EF 命名约定,你如何定义孩子的外键?是否可以使用流利的语法,或者您是否需要为此使用注释?
【解决方案2】:

问题是,它们都在工作!但问题是,我不是 确定哪个是正确的?

是的!您的两种方法都不正确(归功于 Ivan Stoev)。因为:

您的解决方案 1:

HasRequired(t => t.Parent).WithRequiredDependent(t => t.Child);

表示父 1 1 子关系(父必须始终有 1 个子)。

您的解决方案 2:

HasOptional(c => c.Parent).WithRequired(c => c.Child);

表示 Parent 0..1 1 Child 关系(child 可以有 0 或 1 个 parent,parent 必须始终有 1 个 child),即与您想要的相反。

您的 Fluent API 应如下所示:

modelBuilder.Entity<Parent>()
                .HasOptional(p => p.Child) // Mark Child property optional in Parent entity
                .WithRequired(c => c.Parent); // mark Parent property as required in Child entity. Cannot save Child without Parent

此外,您还可以使用 Data Annotation 配置一对一或一对零关系,如下所示:

子类应该如下:

public class Child
{
  [Key,ForeignKey("Parent")]
  public int ParentId { get; set; }
  public string Name { get; set; }
  public virtual Parent Parent { get; set; }
}

【讨论】:

  • 不!如何??父主键也是子主键..表可以有重复的主键吗?绝对不行..
  • 他想要的是一对一或零关系
  • 其他孩子也可以有相同的父键,这将导致一对零或多个!!!
  • 你弄错了..我的代码是一对一或一对零的关系..他到底想要什么..
  • Still downvoted.This answer没有澄清他做错了什么以及为什么,我喜欢的一点是建议一种更常见的配置实体的方法和一种更漂亮的(imo)方法(两者都没有被问到)...
【解决方案3】:

你不需要装饰ForeignKey 属性。如果你想有一个 1 到 0 的关系,关系的一侧必须是可选的(例如:HasOptional),如以下代码:

public class Parent
{
   [Key]
   public int Id { get; set; }
   public string Name { get; set; }
   public virtual Child Child { get; set; }
}

public class Child
{
   [Key]
   public int Id { get; set; }
   public string Name { get; set; }
   public virtual Parent Parent { get; set; }
}



public class ParentMap : EntityTypeConfiguration<Parent>
{
    public ParentMap ()
    {
        HasOptional(t => t.Child).WithRequired(t => t.Parent);
    }
}

现在当您向数据库添加新父级时不需要添加子级,因为它是可选的,但是当您想向数据库添加新子级时,子级Id 必须等于父级Id

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-28
    • 1970-01-01
    • 2017-10-05
    • 1970-01-01
    • 1970-01-01
    • 2017-09-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多