尝试在子类型之间创建关系时出现 EF 迁移 FK 错误
本文关键字:EF 迁移 错误 FK 关系 类型 创建 之间 | 更新日期: 2023-09-27 18:36:52
我的域模型我有一个抽象的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; }
现在是棘手的部分,我的要求是:
- 供应商不得有资金账户
- 经销商必须拥有经销商资金账户
- 零售商必须拥有零售商资金账户
应该是这么简单:
modelBuilder.Entity<Retailer>()
.HasRequired(r => r.FundsAccount)
.WithRequiredDependent(rfa => rfa.Retailer);
modelBuilder.Entity<Dealer>()
.HasRequired(d => d.FundsAccount)
.WithRequiredDependent(dfa => dfa.Retailer);
但是 EF 迁移在尝试更新数据库架构时惨遭失败。由于 TPH,经销商和零售商映射到同一个公司数据库表,而零售商资金帐户和经销商资金帐户映射到资金帐户数据库表,所有这些都是需要的,但由于我在子类型之间定义了两个一对一关系,EF 尝试定义两次资金帐户 ID 字段的外键。
我知道我可以通过为每个具有资金帐户的公司表定义一对多关系来破解解决方案,并在其 FK 中使用独特的约束来防止一对多行为,但我想与您核实是否有更好的解决方案。
事实证明,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 和索引条目。
我还将更新问题的标题,以更好地描述问题。