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方法所必需的?)
在保持架构不变以保留数据库中现有数据的同时,升级这种关系的正确方法是什么?
当前映射生成以下迁移:
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);
希望它能有所帮助!