NHibernate Exception "объект ссылается на несохраненный временный экземпляр - сохраните временный экземпляр перед сбросом" при сохранении объекта с помощью HasMany - PullRequest
1 голос
/ 26 января 2012

Я пытаюсь сохранить объект с несколькими связями 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);

} 

Ответы [ 2 ]

1 голос
/ 26 января 2012

Получите списки перед созданием нового счета-фактуры. Возможно, существует проблема с идентификатором счета-фактуры по умолчанию.

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 голосов
/ 26 января 2012

установка session.Flushmode == FlushMode.Commit поможет.я думаю, GetExpenses() и GetTimeWorked() справочные счета, что приводит к сбросу, чтобы получить правильные данные

...