EF:如何在不更改架构或丢失数据的情况下从独立关联转换为外键关联

本文关键字:关联 情况下 数据 独立 转换 EF | 更新日期: 2023-09-27 18:30:10

我有两个具有双向0对1关系的模型。

A、 B.A可能有B.B可能有A.

目前,这些设置在每个类中都有导航属性,没有外键属性(使用流畅的语法设置)

public class A{
[key]
public int Id {get;set;}
public B B {get;set;}}
public class B{
[key]
public int Id {get;set;}
A A {get;set;}
}
     modelBuilder.Entity<B>()
            .HasOptional(b => b.A)
            .WithOptionalPrincipal()
            .Map(b => b.MapKey("AId"));
        modelBuilder.Entity<A>()
            .HasOptional(p => p.B)
            .WithOptionalPrincipal()
            .Map(p => p.MapKey("BId"));

到目前为止,一切如常。

我现在想在我的实体中公开这些ID属性,以便帮助更新断开连接的实体关系。

当我刚添加属性时,每个错误0019都会出现"重复名称"错误:类型中的每个属性名称在ID字段上都必须是唯一的

如果我移除贴图,然后尝试使用关键帧,它似乎可以工作,但移植决定删除FK列,然后用不同的名称重新添加它们。这将破坏我现有的所有数据。

我试图重写fluent映射以使用HasMany().HasForeignKey(),但这也不起作用。(尽管不是很多,但这似乎是获得HasForeignKey方法所必需的?)

在保持架构不变以保留数据库中现有数据的同时,升级这种关系的正确方法是什么?

EF:如何在不更改架构或丢失数据的情况下从独立关联转换为外键关联

当前映射生成以下迁移:

CreateTable(
    "dbo.B",
    c => new
        {
            Id = c.Int(nullable: false, identity: true),
            BId = c.Int(),
        })
    .PrimaryKey(t => t.Id)
    .ForeignKey("dbo.A", t => t.BId)
    .Index(t => t.BId);
CreateTable(
    "dbo.A",
    c => new
        {
            Id = c.Int(nullable: false, identity: true),
            AId = c.Int(),
        })
    .PrimaryKey(t => t.Id)
    .ForeignKey("dbo.B", t => t.AId)
    .Index(t => t.AId);

正如你所看到的,这是一个1-n的关系,而不是1-0.1。"A可能有B;B可能有A"的关系是不可能的。

A可能有B,但只有一个B,所以B的主键也应该是A的外键。

没关系。这就是1-0.1关系的运作方式。但另一方面,你们也想这么做。

B可能有一个A,但只有一个A。所以A的主键也应该是B的外键。

这不好,你试图建立一个"真正的1-1关系",这是不可能的,因为你不能同时插入两行。

你想要的是一种1-n关系。因此,修改你的类如下:

public class A
{
    [Key]
    public int Id { get; set; }
    public int? BId { get; set; }
    public B B { get; set; }
}
public class B
{
    [Key]
    public int Id { get; set; }
    public int? AId { get; set; }
    public A A { get; set; }
}

映射:

modelBuilder.Entity<A>()
    .HasOptional(i => i.B)
    .WithMany()
    .HasForeignKey(i => i.BId);
modelBuilder.Entity<B>()
    .HasOptional(i => i.A)
    .WithMany()
    .HasForeignKey(i => i.AId);

它生成以下迁移(属性的名称可能颠倒。在这种情况下,只需将BId更改为AId,将AId更改为BId):

CreateTable(
    "dbo.B",
    c => new
        {
            Id = c.Int(nullable: false, identity: true),
            AId = c.Int(),
        })
    .PrimaryKey(t => t.Id)
    .ForeignKey("dbo.A", t => t.AId)
    .Index(t => t.AId);
CreateTable(
    "dbo.A",
    c => new
        {
            Id = c.Int(nullable: false, identity: true),
            BId = c.Int(),
        })
    .PrimaryKey(t => t.Id)
    .ForeignKey("dbo.B", t => t.BId)
    .Index(t => t.BId);

希望它能有所帮助!