尝试在子类型之间创建关系时出现EF-Migrations FK错误

时间:2013-10-25 19:56:57

标签: c# entity-framework ef-code-first ef-migrations table-per-hierarchy

我的域模型我有一个Company基类是抽象的,三个不同的公司类型由公司的子类代表:

public abstract class Company
{
    public int Id { get; set; }
    ...
}

public class Supplier : Company
{
    ...
}

public class Dealer : Company
{
    public DealerFundsAccount FundsAccount { get; set; }
    ...
}

public class Retailer : Company
{
    public RetailerFundsAccount FundsAccount { get; set; }
    ...
}

以同样的方式,我有另一个定义基金账户的基类和两个实现特定属性的子类型:

public abstract class FundsAccount
{
    public int Id { get; set; }
    ...
}

public class DealerFundsAccount : FundsAccount
{
    public Dealer Dealer { get; set; }
    ...
}

public class RetailerFundsAccount : FundsAccount
{
    public Retailer Retailer { get; set; }
    ...
}

我对这些类型的映射策略是每个层次的表,所以在我的DbContext类中,我只为基类定义DbSets,这使我能够执行多态和非多态查询:

public DbSet<Company> Companies { get; set; }
public DbSet<FundsAccount> FundsAccounts { get; set; }

现在是棘手的部分,我的要求说明:

  • 供应商必须拥有资金帐户
  • 经销商必须拥有DealerFundsAccount
  • 零售商必须拥有RetailerFundsAccount

应该这么简单:

modelBuilder.Entity<Retailer>()
    .HasRequired(r => r.FundsAccount)
    .WithRequiredDependent(rfa => rfa.Retailer);

modelBuilder.Entity<Dealer>()
    .HasRequired(d => d.FundsAccount)
    .WithRequiredDependent(dfa => dfa.Retailer);

但EF迁移失败了,试图更新数据库架构。由于TPH,经销商和零售商被映射到相同的公司数据库表,而RetailerFundsAccounts和DealerFundsAccounts被映射到FundsAccount数据库表,所有这些都是期望的,但由于我在子类型之间定义了两个一对一的关系,EF 尝试两次定义FundsAccount Id字段的外键

我知道我可以通过为每个公司表定义一对多关系来破解解决方案,这些关系具有资金帐户,使用FK中的唯一约束来防止一对多行为,但我想检查和你一起,如果有更好的解决方案。

1 个答案:

答案 0 :(得分:0)

原来,EF迁移是罪魁祸首。如果我尝试从头开始创建数据库模式,一切都很好,但如果你创建一个迁移来添加这些实体,EF会因为尝试创建索引和外键两次失败,如下所示:

        CreateTable(
            "dbo.FundsAccount",
            c => new
                {
                    Id = c.Int(nullable: false),
                    Discriminator = c.String(nullable: false, maxLength: 128),
                })
            .PrimaryKey(t => t.Id)
            .ForeignKey("dbo.Company", t => t.Id)
            .ForeignKey("dbo.Company", t => t.Id) // duplicate
            .Index(t => t.Id)
            .Index(t => t.Id); // duplicate

解决方案是编辑迁移,删除重复的FK和索引条目。

我还会更新问题标题以更好地描述问题。