一个或零到一个实体框架代码First Fluent Api

时间:2015-02-13 11:59:21

标签: c# entity-framework ef-code-first ef-fluent-api

  1. 我需要创建一个或0到一个引用的fluentapi,并在两个实体上都有导航属性。
  2. EntityTwo应该包含存储外键的简单proerty(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);
        }
    }
    
  3. 更复杂的情况:

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

2 个答案:

答案 0 :(得分:12)

在一对一关系中,一端必须是主要,第二端必须是依赖。主要末端是首先插入的末端,可以在没有从属末端的情况下存在。从属端是必须在主体之后插入的端,因为它具有主体的外键。配置一对一关系时,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; }
}

我建议你查看link,你可以找到更多关于如何在EF Code First中实现一对一关系的信息。

更新

我担心你想要的东西是不可能的。你不能与未被宣布为PK的FK建立一对一的关系。如果您希望每个实体都有自己的Id,并在这两个实体之间配置一对一的关系,那么删除EntityTwo中的FK属性。

我的推荐是使用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; }
}

答案 1 :(得分: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; }
}