简体   繁体   English

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

[英]Entity Framework 1 to 0 or 1 relationship configuration

I have this class 我有这门课

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

and a child class 和一个儿童班

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

The relation is such that a parent can have either 0 or 1 child. 这种关系使父母可以有0或1个孩子。 I've checked SO and found two solutions. 我检查了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);
    }
}

And the thing is, they are both working ! 事实是,他们都在工作 But the problem is, I am not sure which one is correct. 但问题是, 我不确定哪一个是正确的。 Which one is providing me the mapping that one parent can have only 0 or 1 child. 哪一个给我一个父母只能有0或1个孩子的映射。 And then, what is the other one saying? 那么,另一个人说的是什么?

Let add the related entities to the desired relationship along with their cardinality: 让我们将相关实体添加到所需的关系及其基数:

Parent 1 <--> 0..1 Child 父1 < - > 0..1孩子

You can read it this way: 你可以这样读它:

(1) --> 0..1 Child means that each Parent can have 0 or 1 Child, or in other words, the Child property of the Parent entity is optional (1) - > 0..1 Child表示每个Parent可以有0或1个Child,换句话说, Parent实体的Child属性是可选的

(2) Parent 1 <-- means that each Child always have 1 Parent, or in other words, the Parent property of the Child entity is required . (2) 父1 < -表示每个子节点总是有1个父节点,换句话说, 需要 Child实体的Parent属性。

The fluent configuration which corresponds to the above from Child side is: Child方面相对应的流畅配置是:

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

or alternatively from Parent side: 或者从Parent方那里:

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

These two are the correct ones and fully equivalent - you can use one or the another depending of whether you start the configuration from Child (as in your sample) or from Parent . 这两个是正确的并完全等效 - 您可以使用一个或另一个,具体取决于您是从Child (如样本)还是从Parent启动配置。 To avoid discrepancies, never do both. 为了避免差异,不要两者都做。

Why both your current solutions are incorrect? 为什么您当前的解决方案都不正确?

Because: 因为:

(solution 1) (解决方案1)

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

represents Parent 1 <--> 1 Child relationship (parent must have always 1 child). 表示父1 < - > 1子关系(父亲必须始终有1个孩子)。

(solution 2) (解决方案2)

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

represents Parent 0..1 <--> 1 Child relationship (child can have 0 or 1 parent, parent must have always 1 child), ie the opposite of what you want. 代表父0..1 < - > 1子关系(孩子可以有0或1个父母,父母必须总是1个孩子),即与你想要的相反。

And the thing is, they are both working! 事实是,他们都在工作! But the problem is, I am not sure which one is correct? 但问题是,我不确定哪一个是正确的?

Yes! 是! your both approach is incorrect (Credit goes to Ivan Stoev). 你的两种方法都是不正确的(信用转到Ivan Stoev)。 Because: 因为:

Your solution 1 : 你的解决方案1:

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

represents Parent 1 <--> 1 Child relationship (parent must have always 1 child). 表示父1 < - > 1子关系(父亲必须始终有1个孩子)。

Your solution 2: 你的解决方案2:

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

represents Parent 0..1 <--> 1 Child relationship (child can have 0 or 1 parent, parent must have always 1 child), ie the opposite of what you want. 代表父0..1 < - > 1子关系(孩子可以有0或1个父母,父母必须总是1个孩子),即与你想要的相反。

Your Fluent API should be as follows: 您的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

Moreover you can also configure One-to-One or One-to-Zero relationship with Data Annotation as follows: 此外,您还可以使用Data Annotation配置One-to-One或One-to-Zero关系,如下所示:

Child class should be as follows: 子类应如下:

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

you don't need to decorate ForeignKey attribute. 你不需要修饰ForeignKey属性。 if you want to have a 1 to 0 relation, a side of relation must be optional (ex: HasOptional), like the following code: 如果你想要一个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);
    }
}

now when you add a new parent to the database does not need to add a child because it is optional but when you want to add a new child to the database the child Id must equal with parent Id . 现在,当您向数据库添加新父项时,不需要添加子项,因为它是可选项,但是当您要将新子项添加到数据库时,子项Id必须与父项Id相等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM