c# - 一对一或零对一 Entity Framework 代码优先 FluentApi

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

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

最佳答案

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

关于c# - 一对一或零对一 Entity Framework 代码优先 FluentApi,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28499126/

相关文章:

c# - 如何使用 Entity Framework 中的 Where 计算关联实体

c# - 现有数据库的 Entity Framework 代码优先迁移策略

entity-framework - 模拟或伪造 DbEntityEntry 或创建新的 DbEntityEntry

c# - 我可以在 C# 中扩展 Request 方法吗?

c# - 如何在 C# 中从 Mail Raw header 获取 Message 对象

c# - 获取所有只包含数字 x 和数字 y 的数字

c# - 将 System.Messaging.MessageQueue 或 WCF 用于 MSMQ?

entity-framework - Entity Framework 'Update Model from Database'在基类和子类之间重新创建关联

c# - 如何在 Entity Framework Code-First 中创建自定义 m2m 表

sql-server-2008 - Entity Framework Database.SetInitializer根本不起作用