我正在学习实体框架并在删除记录时与 TPH 作斗争。我创建了如下 POCO
public class Transaction
{
public int Id { get; set; }
public DateTime TransactionDate { get; set; }
public string Item { get; set; }
public double Amount { get; set; }
public virtual PaymentDetail PaymentDetail { get; set; }
}
public class Income : Transaction
{
public string Source { get; set; }
}
public class Expense : Transaction
{
public bool IsAvoidable { get; set; }
}
public class PaymentDetail
{
public int Id { get; set; }
public DateTime PaymentDate { get; set; }
}
public class Cash : PaymentDetail
{
}
public class BankTransfer : PaymentDetail
{
public string TransactionNumber { get; set; }
}
public class BankCheque : PaymentDetail
{
public string ChequeNumber { get; set; }
}
public class Card : PaymentDetail
{
public BankAccount BankAccount { get; set; }
}
在我的 DbContext 中,我重写了 OnModelCreating 方法。我在那里有以下代码。
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>().ToTable("User");
modelBuilder.Entity<Transaction>().ToTable("Transaction");
modelBuilder.Entity<Income>().ToTable("Income");
modelBuilder.Entity<Expense>().ToTable("Expense");
modelBuilder.Entity<PaymentDetail>().ToTable("PaymentDetail");
modelBuilder.Entity<Liability>().ToTable("Liability");
modelBuilder.Entity<Transaction>().HasOptional(p => p.PaymentDetail);
}
我已经编写了插入和更新事务的代码。插入工作正常。它使用 paymentDetail(作为现金)创建交易。但是当我更新它并将 PaymentDetail 更改为 BankTransfer 时,它会更新 PaymentDetail 中的详细信息(这是一个作为 TPH 创建的平面表)。但它不会更改鉴别器列。它仍然是 Cash,因为它最初是使用 Cash 类型创建的。我通过谷歌搜索发现鉴别器列没有改变。所以我试图删除该行,但它现在给出了以下错误
DELETE 语句与 REFERENCE 约束“FK_dbo.Transaction_dbo.PaymentDetail_PaymentDetail_Id”冲突。冲突发生在数据库“MyRecordsDB”、表“dbo.Transaction”、列“PaymentDetail_Id”中。该语句已终止。
EF代码创建的TransactionTable首先有PaymentDetail_ID可以有allow null,那么谁能告诉我这个问题吗?
在这种情况下使用 TPH 好不好?
以下是从我的 RepositoryClass 修改 Transaction 的方法供参考。
public Transaction ModifyTransaction(Transaction tran)
{
using (_ctx = new Context())
{
tran = _ctx.Transactions.Attach(tran);
//Check if the Payment detail is modified
if(tran.PaymentDetail != null)
{
PaymentDetail currentPaymentDetail = null;
using (var ctx = new Context())
{
currentPaymentDetail = ctx.PaymentDetails.Where(p => p.Id == tran.PaymentDetail.Id).FirstOrDefault();
if (currentPaymentDetail.GetType() != tran.PaymentDetail.GetType())
{
//Remove current payment detail record
ctx.PaymentDetails.Remove(currentPaymentDetail);
ctx.SaveChanges();
_ctx.Entry<PaymentDetail>(tran.PaymentDetail).State = EntityState.Added;
}
}
}
else
{
//Do not modify the Payment detail
_ctx.Entry<PaymentDetail>(tran.PaymentDetail).State = EntityState.Unchanged;
}
_ctx.Entry<Transaction>(tran).State = EntityState.Modified;
_ctx.Entry<Profile>(tran.profile).State = EntityState.Unchanged;
_ctx.SaveChanges();
}
return tran;
}