【发布时间】:2012-02-19 05:46:27
【问题描述】:
我正在尝试保存具有多个 HasMany 关系的对象,但出现异常:“对象引用了未保存的瞬态实例 - 在刷新之前保存瞬态实例”。
以下是我的简化类、它们对应的映射以及我的“应用程序”代码。
“申请代码”部分显示了我想要执行的操作:将费用报告和工作时间添加到发票,然后保存发票。
但是,异常发生在 GetTimeWorked() 中。如果我颠倒顺序(在费用报告之前添加工作时间),则会在 GetExpenseReports() 中发生错误。
如果我在添加费用报告后保存发票,然后在添加工作时间后再次保存,它工作正常。但是,这种保存需要是事务性的:费用报告和工作时间必须一起保存。
我已经阅读了很多有关此异常的信息,但我尝试的任何方法都不起作用。我读到的情况似乎与此略有不同。我猜这是一个映射问题,我尝试了一些替代映射(在 HasMany 方面,使用 Cascade),但我不知所措。
知道这里发生了什么以及如何解决它吗?
谢谢!
// Classes
public class TimeWorked {
public virtual long Id { get; private set; }
public virtual float Hours { get; set; }
public virtual Invoice Invoice { get; set; }
}
public class ExpenseReport {
public virtual long Id { get; set; }
public virtual IList<Expense> Expenses { get; set; }
public virtual Invoice Invoice { get; set; }
}
public class Invoice {
public virtual long Id { get; set; }
public virtual IList<ExpenseReport> ExpenseReports { get; set; }
public virtual IList<TimeWorked> BilledTime { get; set; }
public virtual void AddExpenseReport(List<ExpenseReport> expenseReports)
{
foreach (ExpenseReport er in expenseReports)
{
ExpenseReports.Add(er);
er.Invoice = this;
}
}
public virtual void AddTimeWorked(List<TimeWorked> timeWorked)
{
foreach (TimeWorked tw in timeWorked)
{
BilledTime.Add(tw);
tw.Invoice = this;
}
}
}
// Mapping
public class TimeWorkedMapping : ClassMap<TimeWorked>
{
public TimeWorkedMapping()
{
Id(x => x.Id);
References(x => x.Invoice);
}
}
public class ExpenseReportMapping : ClassMap<ExpenseReport>
{
public ExpenseReportMapping()
{
// Primary Key
Id(x => x.Id);
HasMany(x => x.Expenses).Cascade.AllDeleteOrphan();
References(x => x.Invoice);
}
}
public class InvoiceMapping : ClassMap<Invoice>
{
public InvoiceMapping()
{
Id(x => x.Id);
HasMany(x => x.ExpenseReports).Inverse();
HasMany(x => x.BilledTime).Inverse();
}
}
// Application Code
public class MyPage
{
// Do stuff...
Invoice invoice = new Invoice();
// Add the expense reports
List<ExpenseReport> erList = GetExpenseReports();
invoice.AddExpenseReport(erList);
// Add billable time
List<TimeWorked> twList = GetTimeWorked(); <<== Exception occurs in here
invoice.AddTimeWorked(twList);
// Save invoice
Save(invoice);
}
【问题讨论】:
-
您的备用映射是什么(使用 HasMany 级联)?此外,GetExpanseReports 和 GetTimeWorked 带回现有数据?未连接到任何发票?
-
Mush 先生:在发票映射中,我尝试了
Cascade.SaveUpdate()用于ExpenseReports和BilledTime。 Get 方法确实会带回尚未分配给发票的现有数据。但是,在上面的代码中,invoice.AddExpenseReport(erList)会影响发票本身。以下对GetTimeWorked()的方法调用获取了未分配发票的TimeWorked 对象,但不知何故NHB 不高兴,因为invoice已被修改。 -
您能否尝试在创建新发票之前获取列表并在创建发票后连接它们?默认发票 ID 可能存在一些问题。
-
很好的建议,成功了! (而且我使用了我原来的映射,所以不需要
Cascade.SaveUpdate())。谢谢!
标签: nhibernate nhibernate-mapping fluent-nhibernate-mapping