我正在学习实体框架,并在删除记录时与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的平面表)。但它不会改变鉴别器列。它仍然是首次使用现金类型创建的现金。 我通过谷歌搜索发现Discriminator列没有改变。所以我试图删除该行,但它现在给出了以下错误
DELETE语句与REFERENCE约束冲突 “FK_dbo.Transaction_dbo.PaymentDetail_PaymentDetail_Id”。冲突 发生在数据库“MyRecordsDB”,表“dbo.Transaction”,列中 'PaymentDetail_Id'。声明已经终止。
由EF代码创建的TransactionTable首先具有PaymentDetail_ID可以允许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;
}