1

我試圖用多個HasMany關係保存一個對象,並且我得到異常:「對象引用未保存瞬態實例 - 在沖洗前保存瞬態實例「。當用HasMany保存對象時,NHibernate異常「對象引用一個未保存的瞬態實例 - 在刷新之前保存瞬態實例」

下面是我的簡化類,它們的相應映射和我的「應用程序」代碼。

「應用程序代碼」部分顯示我想要執行的操作:將開支報告和工作時間添加到發票,然後保存發票。

但是,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); 

} 
+0

什麼是您的替代映射(與HasMany級聯)?另外,GetExpanseReports和GetTimeWorked帶回現有數據?未連接到任何發票? –

+0

Mush先生:在Invoice映射中,我爲'ExpenseReports'和'BilledTime'嘗試了'Cascade.SaveUpdate()'。 Get方法確實還原尚未分配給發票的現有數據。但是,在上面的代碼中,'invoice.AddExpenseReport(erList)'會影響發票本身。下面的方法調用'GetTimeWorked()'得到沒有分配發票的TimeWorked對象,但不知何故NHB不滿意,因爲'發票'已被修改。 – leahcimp

+1

您可以嘗試在創建新發票之前獲取清單,並在創建發票後連接它們?默認發票編號可能存在​​問題。 –

回答

1

在創建新發票前取出列表,可能是默認發票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); 
0

setting session.Flushmode == FlushMode.Commit will help。我猜GetExpenses()GetTimeWorked()參考發票導致刷新以獲取正確的數據

相關問題