实体框架1到0或1关系配置

时间:2018-03-15 17:39:22

标签: c# entity-framework

我有这个班级

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个孩子的映射。那么,另一个人说的是什么?

3 个答案:

答案 0 :(得分:6)

让我们将相关实体添加到所需的关系及其基数:

父母1&lt; - &gt; 0..1孩子

您可以这样阅读:

(1) - &gt; 0..1孩子表示每个父母可以拥有0或1个孩子,换句话说,Child实体的Parent属性可选 < / p>

(2)父1&lt; - 表示每个Child总是有1个Parent,换句话说,Parent实体的Child属性是<强>需要

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);

表示父1&lt; - &gt; 1个孩子关系(父母必须总是1个孩子)。

(解决方案2)

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

表示父级0..1&lt; - &gt; 1孩子关系(孩子可以有0或1个父母,父母必须总是1个孩子),即与你想要的相反。

答案 1 :(得分:4)

  

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

是的!你的两种方法都是不正确的(信用转到Ivan Stoev)。这是因为:

您的解决方案1:

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

表示父1 - &lt; - &gt;。 1子女关系(父母必须总是1个孩子)。

您的解决方案2:

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

代表父0..1&lt; - &gt; 1子女关系(孩子可以有0或1个父母,父母必须总是1个孩子),即与你想要的相反。

您的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

此外,您还可以使用数据注释配置一对一或一对一关系,如下所示:

子类应如下:

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

答案 2 :(得分:1)

您无需修饰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必须与父项{{1}相等}}