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

时间:2016-01-12 16:09:02

标签: c# entity-framework foreign-keys

我有两个具有双向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属性,以帮助更新断开的实体关系。

当我添加属性时,每error 0019: Each property name in a type must be unique on ID field

我会收到“重复名称”错误

如果我删除了地图,然后尝试使用这些键,它似乎可以工作,但迁移决定删除FK列,然后使用其他名称重新添加它们。这将破坏我现有的所有数据。

我尝试重写fluent映射以使用HasMany()。HasForeignKey(),但这也不起作用。 (即使它不是很多,似乎需要获得HasForeignKey方法?)

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

1 个答案:

答案 0 :(得分:0)

您当前的映射会生成以下迁移:

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。关系&#34; A可能有B; B可能有一个A&#34;不可能。

A可能有B,但只有一个B,因此B&#39的主键也应该是A的外键。

没关系。这就是1-0.1关系的运作方式。但另一方面,你想做同样的事情。

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

那不行,你正试图建立一个真正的1-1关系&#34;,这是不可能的,因为你不能同时插入2行。< / p>

你想要的是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);

它会生成以下迁移(属性&#39;名称可能会被反转。在这种情况下,只需将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);

希望它有所帮助!