【问题标题】:One or Zero to One Entity Framework Code First FluentApi一对一或零对一实体框架代码优先 Fluent Api
【发布时间】:2015-04-14 11:12:30
【问题描述】:
  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);
    }
}

【问题讨论】:

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


【解决方案1】:

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

【讨论】:

  • 这个例子是有效的,但是它不符合我的期望。我希望 EntityTwo 有自己的 Id,并带有指向其他实体的链接(每个链接都是唯一的)
  • 你好@OlegGochachko。我前段时间更新了我的答案。您是否尝试过该配置?
  • “您不能与未声明为 PK 的 FK 创建一对一关系。”通过 SQL,FK 是候选键之一就足够了。
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-15
    • 2013-04-16
    • 1970-01-01
    • 2017-05-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多