NHibernate例外情况“;对象引用未保存的临时实例-在刷新之前保存临时实例;使用HasMany保存对象时

NHibernate例外情况“;对象引用未保存的临时实例-在刷新之前保存临时实例;使用HasMany保存对象时,nhibernate,nhibernate-mapping,fluent-nhibernate-mapping,Nhibernate,Nhibernate Mapping,Fluent Nhibernate Mapping,我试图保存一个具有多个HasMany关系的对象,但得到了一个异常:“对象引用了一个未保存的临时实例-在刷新之前保存临时实例” 下面是我的简化类、它们对应的映射和我的“应用程序”代码 “应用程序代码”部分显示了我要执行的操作:将费用报告和工作时间添加到发票,然后保存发票 但是,GetTimeWorked()中发生异常。如果我颠倒顺序(在费用报告之前添加工作时间),则错误发生在GetExpenseReports()中 如果在添加费用报告后保存发票,然后在添加工作时间后再次保存发票,则效果良好。但是,

我试图保存一个具有多个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);

} 
//类
公共课计时{
公共虚拟长Id{get;private set;}
公共虚拟浮动小时数{get;set;}
公共虚拟发票{get;set;}
}
公共类支出报告{
公共虚拟长Id{get;set;}
公共虚拟IList费用{get;set;}
公共虚拟发票{get;set;}
}
公共类发票{
公共虚拟长Id{get;set;}
公共虚拟IList ExpenseReports{get;set;}
公共虚拟IList BilledTime{get;set;}
公共虚拟虚空AddExpenseReport(列出支出报告)
{
foreach(expenseReports中的ExpenseER报告)
{
费用报告。添加(er);
呃,发票=这个;
}
}
公共虚拟void AddTimeWorked(列表timeWorked)
{
foreach(时间工作中的时间工作tw)
{
计费时间。添加(tw);
tw.发票=此;
}
}       
}
//映射
公共类TimeWorkedMapping:ClassMap
{
公共时间工作映射()
{
Id(x=>x.Id);
参考文件(x=>x.发票);
}
}
公共类ExpenseReportMapping:ClassMap
{
公共支出报告映射()
{
//主键
Id(x=>x.Id);
HasMany(x=>x.Expenses);
参考文件(x=>x.发票);
}
}
公共类InvoiceMapping:ClassMap
{
公共发票映射()
{
Id(x=>x.Id);
HasMany(x=>x.ExpenseReports).Inverse();
HasMany(x=>x.BilledTime).Inverse();
}
}
//应用程序代码
公共类MyPage
{
//做些事情。。。
发票=新发票();
//添加费用报告
List erList=GetExpenseReports();
发票.附加费用报告(电子清单);
//添加计费时间

List twList=GetTimeWorked();在创建新发票之前获取列表,默认发票ID可能有问题

List<TimeWorked> twList = GetTimeWorked();
List<ExpenseReport> erList = GetExpenseReports();
Invoice invoice = new Invoice();

// Add the expense reports                       
invoice.AddExpenseReport(erList);

// Add billable time  
invoice.AddTimeWorked(twList);

// Save invoice
Save(invoice);
List twList=GetTimeWorked();
List erList=GetExpenseReports();
发票=新发票();
//添加费用报告
发票.附加费用报告(电子清单);
//添加计费时间
发票。AddTimeWorked(twList);
//保存发票
保存(发票);

在创建新发票之前获取列表,默认发票ID可能有问题

List<TimeWorked> twList = GetTimeWorked();
List<ExpenseReport> erList = GetExpenseReports();
Invoice invoice = new Invoice();

// Add the expense reports                       
invoice.AddExpenseReport(erList);

// Add billable time  
invoice.AddTimeWorked(twList);

// Save invoice
Save(invoice);
List twList=GetTimeWorked();
List erList=GetExpenseReports();
发票=新发票();
//添加费用报告
发票.附加费用报告(电子清单);
//添加计费时间
发票。AddTimeWorked(twList);
//保存发票
保存(发票);

设置会话。Flushmode==Flushmode.Commit会有帮助。我想
GetExpenses()
GetTimeWorked()
引用发票,这会导致刷新以获得正确的数据设置会话。Flushmode==Flushmode.Commit会有帮助。我想
GetExpenses()
GetTimeWorked()
参考发票,这会导致刷新以获得正确的数据

您的替代映射是什么(使用HasMany级联)?另外,GetExpanseReports和GetTimeWorked会带回现有数据?与任何发票都没有连接?穆什先生:在发票映射上,我尝试了
级联.SaveUpdate()
用于
ExpenseReports
BilledTime
。Get方法会带回尚未分配给发票的现有数据。但是,在上述代码中,
invoice.AddExpenseReport(erList)
会影响发票本身。以下方法调用
GetTimeWorked()
获取未分配发票的时间工作对象,但不知何故NHB不高兴,因为
发票
已被修改。您能否在创建新发票之前获取列表,并在创建发票后将其连接起来?默认发票ID可能存在一些问题。很好的建议,这很有效!(我使用了我的原始映射,因此没有必要使用
Cascade.SaveUpdate()
)。谢谢!您的替代映射是什么(使用HasMany Cascade)?另外,GetExpanseReports和GetTimeWorked会带回现有数据?与任何发票都没有连接?穆什先生:在发票映射上,我尝试了
Cascade.SaveUpdate()
用于
ExpenseReports
BilledTime
。Get方法会带回尚未分配给发票的现有数据。但是,在上述代码中,
invoice.AddExpenseReport(erList)
会影响发票本身。以下方法调用
GetTimeWorked()
在未分配发票的情况下获取时间工作对象,但不知怎的,NHB不高兴