我正在使用TPH(按表分层结构)策略创建数据层次结构,并且在将TPH与表的自引用结合使用方面遇到了一些严重的问题。
为澄清起见:我正在使用EF6 Code First。
因此,事不宜迟,整个结构包含3个类:
最简单的想法是,具有一定池(例如100 $)的债务可以包含多个付款,这些付款以后将总计并覆盖(例如20 $,50 $,30 $)。
public abstract class Transaction
{
[Key]
public int Id { get; set; }
public decimal MoneyPool { get; set; }
public DateTime Date { get; set; }
}
public class Debt : Transaction
{
public int DebtorId { get; set; }
public Debtor Debtor { get; set; }
public string Description { get; set; }
public ICollection<Transaction> Payments { get; set; }
}
public class Payment : Transaction
{
public int? DebtId { get; set; }
public Debt Debt { get; set; }
}
从理论上讲,TPH是EF的默认继承实现模式,但出于我的考虑,我在OnModelCreating中手动添加了映射,以便在需要时可以进行一些更改。
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Transaction>()
.Map<Debt>(d => d.Requires("Discriminator").HasValue("Debt"));
modelBuilder.Entity<Transaction>()
.Map<Payment>(d => d.Requires("Discriminator").HasValue("Payment"));
base.OnModelCreating(modelBuilder);
}
现在,好消息是,获得/过账债务并对其进行约束性付款就可以了。
我希望能够删除债务并手动指定如何处理其子付款(付款)-可以级联删除它们或使FK属性无效。
我想检查初始化模型时EF为我设置的操作,因此在SQL Server Management Studio中运行sp_help Transactions
,并注意到默认情况下,delete_action和update_action都设置为“ NO ACTION”如果是这样的自我表引用。
知道我试图手动更改它:
所有这些结果都具有相同的错误:
在表“事务”上引入外键约束'FK_dbo.Transactions_dbo.Transactions_Debt_Id'可能会导致循环或多个级联路径。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY约束。
起初有些令人惊讶,因为这正是我要尝试的完全-启用多个级联路径。但是由于某种原因,我不能。
我最后尝试做的是在覆盖的 OnModelCreating 中配置债务与付款之间的关系。
modelBuilder.Entity<Transaction>()
.Map<Payment>(d => d.Requires("Discriminator").HasValue("Payment"))
.HasOptional(t => (t as Payment).Debt)
.WithMany(t => (t as Debt).Payments)
.WillCascadeOnDelete(true);
与此有关,我得到一个错误,指出(t为T)。属性不是指向属性的有效方法。但是,正如您可能已经知道的那样,如果没有演员表,我将根本无法访问conrete类的属性。
我完全陷入了困境。有谁能解决这个问题?我希望至少能够将delete_action设置为 cascade 或 set null ,update_action的优先级较低,因为仅当有人更改主键时才会发生,无论如何,这是极不可能发生的。