【问题标题】:Entity Framework Code First - Optional/required two-way navigation实体框架代码优先 - 可选/必需的双向导航
【发布时间】:2015-09-06 14:22:57
【问题描述】:

我有一个类似于以下的代码优先模型:

public class TestContext : DbContext
{
    public DbSet<Class1> Class1s { get; set; }
    public DbSet<Class2> Class2s { get; set; }
}

public class Class1
{
    public int Class1Id { get; set; }
}

public class Class2
{
    public int Class2Id { get; set; }

    public int Class1Id { get; set; }
    public Class1 Class1 { get; set; }
}

有零到多个 Class2 对象引用每个 Class1 对象。每个 Class2 对象都必须引用 Class1 对象。

我想做的是有一个从 Class1 到 Class2 的可选引用(以跟踪与 Class1 对象关联的 Class2 对象之一),所以我添加了两个属性:

public class Class1
{
    public int Class1Id { get; set; }
    public int? Class2Id { get; set; }
    public Class2 Class2 { get; set; }
}

现在我在运行 Add-Migration 时收到以下错误:

无法确定之间关联的主体端 类型“ConsoleApplication15.Class2”和“ConsoleApplication15.Class1”。 此关联的主体端必须显式配置 使用关系流式 API 或数据注释。

其他 StackOverflow 答案表明解决方案是在依赖项上指定外键字段:

public class Class2
{
    [Key, ForeignKey("Class1")]
    public int Class2Id { get; set; }

    public int Class1Id { get; set; }
    public Class1 Class1 { get; set; }
}

我的添加迁移命令现在完成了,但是迁移创建如下:

public override void Up()
{
    DropForeignKey("dbo.Class2", "Class1Id", "dbo.Class1");
    DropIndex("dbo.Class2", new[] { "Class1Id" });
    DropColumn("dbo.Class2", "Class2Id");
    RenameColumn(table: "dbo.Class2", name: "Class1Id", newName: "Class2Id");
    DropPrimaryKey("dbo.Class2");
    AddColumn("dbo.Class1", "Class2Id", c => c.Int());
    AlterColumn("dbo.Class2", "Class2Id", c => c.Int(nullable: false));
    AddPrimaryKey("dbo.Class2", "Class2Id");
    CreateIndex("dbo.Class2", "Class2Id");
    AddForeignKey("dbo.Class2", "Class2Id", "dbo.Class1", "Class1Id");
}

这看起来不像我想要的。它正在删除 Class2 上的主键,它在最后添加的外键完全错误。

如何向 EF 描述我的要求,以便它生成正确的模型?

【问题讨论】:

    标签: entity-framework ef-code-first foreign-keys entity-framework-6 foreign-key-relationship


    【解决方案1】:

    问题是 EF 按照惯例您要创建一个one-to-one relationship,在这种情况下您需要指定哪个实体是主体。

    如果您想在每个实体中创建具有不同 PK 的一对一关系,则不能在两个实体中声明 FK 属性。当您配置 one-to-one relationships 时,Entity Framework 要求依赖项的主键也是外键(这是您在上一个场景中尝试做的)。

    一种解决方案可能是删除 FK 属性(Class2 上的 Class1IdClass1 上的 Class2Id)并在您的上下文中覆盖 OnModelCreating 方法以添加此配置:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
         modelBuilder.Entity<Class2>()
                     .HasRequired(c2 => c2.Class1).
                     .WithOptional(c1=>c1.Class2);
    }
    

    如果您想使用 FK 属性,您可以创建两个单独的关系,如下所示:

            modelBuilder.Entity<Class2>()
                        .HasRequired(s => s.Class1)
                        .WithMany()
                        .HasForeignKey(s => s.Class1Id);
    
            modelBuilder.Entity<Class1>()
                        .HasOptional(s => s.Class2)
                        .WithMany()
                        .HasForeignKey(s => s.Class2Id);
    

    我认为最后一个解决方案更适合您想要实现的场景。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多