Исключение NHibernate: не удалось инициализировать коллекцию, неверное имя столбца. Свободное картографирование. Может, проблема со многими к одному?

Я озадачен и расстроен исключением, которое я получаю через NHibernate. Я прошу прощения за длину этого поста, но я попытался включить соответствующий уровень детализации, чтобы объяснить проблему достаточно хорошо, чтобы получить некоторую помощь!

Вот факты:

  • У меня есть класс Person, который содержит свойство BillingManager, которое также относится к типу Person. Я сопоставляю это как FNH «Reference».
  • У меня есть класс ExpenseReport, который содержит свойство SubmittedBy типа Person. Я сопоставляю это как FNH «Reference».
  • У меня есть класс BillableTime, который содержит свойство Person типа Person. Я сопоставляю это как FNH «Reference».
  • Person содержит коллекцию (IList) ExpenseReport типов (свойство ExpenseReports)
  • Person содержит коллекцию (IList) BilledTime типов (свойство Time)

(См. классы и сопоставления внизу сообщения.)

Все было круто, пока я не добавил коллекцию IList<BilledTime> Time в Person. Теперь, когда я пытаюсь получить доступ к _person.Time, я получаю исключение:

Код:

// Get billable hours
if (_person.Time == null || 
    _person.Time.Count(x => x.Project.ProjectId == project.ProjectId) == 0)
{
    // No billable time for this project
    billableHours = Enumerable.Repeat(0F, 14).ToArray();
}

Исключение:

could not initialize a collection: 
[MyApp.Business.Person.Time#211d3567-6e20-4220-a15c-74f8784fe47a]
[SQL: SELECT 
time0_.BillingManager_id as BillingM8_1_, 
time0_.Id as Id1_, 
time0_.Id as Id1_0_, 
time0_.ReadOnly as ReadOnly1_0_, 
time0_.DailyHours as DailyHours1_0_, 
time0_.Week_id as Week4_1_0_, 
time0_.Person_id as Person5_1_0_, 
time0_.Project_id as Project6_1_0_, 
time0_.Invoice_id as Invoice7_1_0_ 
FROM [BillableTime] time0_ 
WHERE time0_.BillingManager_id=?]

Это правда, что BillingManager_id — недопустимое имя столбца, его нет в таблице BillableTime. Однако я не понимаю, почему NHB создал этот SQL... для меня это не имеет смысла. Я часто видел это исключение «Недопустимое имя столбца» при поиске решения, но, похоже, ничего не работает. Еще более запутанно: как и BilledTime, тип ExpenseReport также содержит ссылку на Person и работает отлично.

Одна вещь, которую я смог выяснить, заключается в том, что если я удалю ссылку BillingManager из сопоставления Person (References(p => p.BillingManager)), исключение исчезнет, ​​и все, кажется, работает (в отношении BillableTime; это, конечно, нарушает постоянство BillingManager). Теперь кажется, что есть некоторая проблема с «самоссылкой», поскольку свойство Person.BillingManager само по себе является ссылкой на Person.

Любая идея, что здесь происходит? Я в растерянности...

Спасибо.

=== Классы и сопоставления ===

public class Person
{
    public virtual string LastName { get; set; }
    public virtual string FirstName { get; set; }

    public virtual Person BillingManager { get; set; }

    public virtual IList<ExpenseReport> ExpenseReports { get; set; }
    public virtual IList<BillableTime> Time { get; set; }
}


public class PersonMapping : ClassMap<Person> 
{        
    public PersonMapping()
    {
        Id(p => p.UserId).GeneratedBy.Assigned();
        Map(p => p.LastName).Not.Nullable();
        Map(p => p.FirstName).Not.Nullable();

        References(p => p.BillingManager);

        HasMany(p => p.ExpenseReports).Cascade.AllDeleteOrphan();
        HasMany(p => p.Time).Cascade.AllDeleteOrphan(); 
    }
}

public class BillableTime
{
    public virtual int Id { get; private set; }
    public virtual Week Week { get; set; }
    public virtual Person Person { get; set; }
    public virtual Project Project { get; set; }
    public virtual float[] DailyHours { get; set; }
    public virtual Invoice Invoice { get; set; }
    public virtual bool ReadOnly { get; set; }
}       

public class BillableTimeMapping : ClassMap<BillableTime>
{
    public BillableTimeMapping()
    {
        Id(x => x.Id);
        References(x => x.Week);
        References(x => x.Person);
        References(x => x.Project);
        References(x => x.Invoice);
        Map(x => x.ReadOnly).Not.Nullable().Default("0");
        Map(x => x.DailyHours).Length(28);  
    }
}


public class ExpenseReport
{
    public virtual long Id { get; set; }        
    public virtual Person SubmittedBy { get; set; }             
}

person realmikep    schedule 07.10.2011    source источник
comment
это изменится, если вы укажете HasMany(p => p.Time).Cascade.AllDeleteOrphan().KeyColumn("Person_Id");?   -  person Firo    schedule 07.10.2011
comment
Это так, спасибо! Раньше я пытался использовать KeyColumn, но, возможно, я неправильно понял его использование. Я думал, что он указывает ключевой столбец для таблицы BillableTime, но теперь я думаю, что он указывает Person FK в BillableTime. Это правильно? И есть идеи, как NHB определил (неправильно), что BillingManager_id был FK? Просто пытаюсь понять это лучше.   -  person realmikep    schedule 07.10.2011


Ответы (1)


следующая строка должна решить проблему, но я точно не знаю, почему это происходит. если у меня будет свободное время, я буду исследовать.

HasMany(p => p.Time).Cascade.AllDeleteOrphan().KeyColumn("Person_Id");
person Firo    schedule 07.10.2011