在我的域模型中,我有一个Company
抽象的基类和由 Company 的子类表示的三种不同的 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; }
...
}
同样,我还有另一个基类,它定义了 Funds Account 和两个实现特定属性的子类型:
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 类中,我只为基类定义 DbSet,这使我能够执行多态和非多态查询:
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 Migrations 在尝试更新数据库架构时惨遭失败。由于 TPH,Dealers 和 Retailers 映射到同一个 Company 数据库表,而 RetailerFundsAccounts 和 DealerFundsAccounts 映射到 FundsAccount db 表,所有这些都是需要的,但由于我在子类型之间定义了两个一对一的关系,EF尝试定义 FundsAccount Id 字段的外键两次。
我知道我可以通过为每个具有资金帐户的 Company 表定义一对多关系来破解解决方案,并使用其 FK 中的唯一约束来防止一对多行为,但我想与你核实一下有一个更好的解决方案。