8
  1. 我需要创建 fluentapi 一对一或零对一引用,并在两个实体上都具有导航属性。
  2. EntityTwo 应该包含简单的属性来存储外键 (EntityOneId)

    public class EntityOne
    {
        public int Id { get; set; }
        public EntityTwo EntityTwo { get; set; }
    }
    
    public class EntityTwo
    {
        public int Id { get; set; }
        public int EntityOneId { get; set; }
        public EntityOne EntityOne { get; set; }
    }
    
    public class MyDbContext : DbContext
    {
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            //some code trimmed
    
            modelBuilder.Entity<EntityOne>()
                .HasOptional(entity => entity.EntityTwo)
                .WithRequired();
    
            modelBuilder.Entity<EntityTwo>()
                .HasRequired(entity => entity.EntityOne)
                .WithMany()
                .HasForeignKey(entity => entity.EntityOneId)
                .WillCascadeOnDelete(false);
        }
    }
    

更复杂的场景:

public class EntityOne
{
    public int Id { get; set; }

    public EntityTwo EntityTwo { get; set; }
}

public class EntityThree
{
    public int Id { get; set; }

    public EntityTwo EntityTwo { get; set; }
}

public class EntityTwo
{
    public int Id { get; set; }

    public int EntityOneId { get; set; }

    public EntityOne EntityOne { get; set; }

    public int EntityThreeId { get; set; }

    public EntityThree EntityThree { get; set; }
}

public class MyDbContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        //some code trimmed

        modelBuilder.Entity<EntityOne>()
            .HasOptional(entity => entity.EntityTwo)
            .WithRequired();

        modelBuilder.Entity<EntityThree>()
            .HasOptional(entity => entity.EntityTwo)
            .WithRequired();

        modelBuilder.Entity<EntityTwo>()
            .HasRequired(entity => entity.EntityOne)
            .WithMany()
            .HasForeignKey(entity => entity.EntityOneId)
            .WillCascadeOnDelete(false);

        modelBuilder.Entity<EntityTwo>()
            .HasRequired(entity => entity.EntityThree)
            .WithMany()
            .HasForeignKey(entity => entity.EntityThreeId)
            .WillCascadeOnDelete(false);
    }
}
4

2 回答 2

13

在一对一的关系中,一端必须是主体,而另一端必须是从属的。主端是最先插入的端,它可以在没有依赖端的情况下存在。依赖端是必须插入主体之后的端,因为它具有主体的外键。配置一对一关系时,Entity Framework 要求依赖的主键也是外键。实现您想要的正确方法可能是这样,但使用数据注释:

public class EntityOne
{
  public int Id { get; set; }
  public virtual EntityTwo EntityTwo { get; set; }
}

 public class EntityTwo
 {
   [Key, ForeignKey("EntityOne")]
   public int EntityOneId { get; set; }
   public virtual EntityOne EntityOne { get; set; }
}

我建议你检查这个链接,你可以找到更多关于如何在 EF Code First 中工作的一对一关系的信息。

更新:

恐怕您想要的东西是不可能的。您无法与未声明为PK的FK创建一对一的关系。如果你想让每个实体都有自己的Id一个配置这两个实体之间的一对一关系,那么删除EntityTwo.

我的建议是使用 Fluent Api 映射该关系,如下所示:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<EntityTwo>()
        .HasRequired(et => et.EntityOne)
        .WithOptional(eo=>eo.EntityTwo);
}

或者,您可以在Required作为主体的导航属性上添加属性,例如:

public class EntityTwo
{
  public int Id { get; set; }
  // public int EntityOneId { get; set; }
  [Required]
  public EntityOne EntityOne { get; set; }
}
于 2015-02-13T14:34:23.210 回答
0

我想出的唯一方法是创建一个集合和一个辅助属性来表示一/零侧,这无疑有点难看。为清楚起见,包括数据注释。

public class EntityOne
{
    [Key]
    public int EntityOneId { get; set; }

    public EntityTwo EntityTwo => EntityTwoNavigation?.FirstOrDefault();
    public ICollection<EntityTwo> EntityTwoNavigation { get; set; }
}

public class EntityTwo
{
    [Key]
    public int EntityTwoId { get; set; }
    public int EntityOneId { get; set; }

    [ForeignKey("EntityOneId")]
    public EntityOne EntityOne { get; set; }
}
于 2017-06-21T21:37:44.320 回答