NHibernate 异常:无法初始化集合,列名无效。流畅的映射。也许是多对一的问题?

发布于 2024-12-08 20:26:04 字数 3913 浏览 0 评论 0原文

我对通过 NHibernate 遇到的异常感到困惑和沮丧。对于这篇文章的篇幅,我深表歉意,但我已尝试提供适当的详细信息来充分解释该问题,以获得一些帮助!

事实是这样的:

  • 我有一个 Person 类,其中包含一个 BillingManager 属性,它也是一个 Person 类型。我将其映射为 FNH“参考”。
  • 我有一个 ExpenseReport 类,其中包含一个 SubscribedBy 属性,它是一个 Person 类型。我将其映射为 FNH“参考”。
  • 我有一个 BillableTime 类,其中包含一个 Person 属性,它是一个 Person 类型。我将其映射为 FNH“参考”。
  • Person 包含 ExpenseReport 类型的集合 (IList)(属性 ExpenseReports
  • Person 包含以下类型的集合 (IList) BilledTime 类型(属性 Time

(请参阅帖子底部的类和映射。)

一切都很酷,直到我添加了 IList。时间集合到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 的引用,并且它工作得很好。

我能弄清楚的一件事是,如果我从 Person 映射中删除 BillingManager 引用 (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; }             
}

I am puzzled and frustrated by an exception I'm getting via NHibernate. I apologize for the length of this post, but I've tried to include an appropriate level of detail to explain the issue well enough to get some help!

Here's the facts:

  • I have a Person class which contains a property BillingManager, which is also a Person type. I map this as an FNH "Reference".
  • I have an ExpenseReport class which contains a property SubmittedBy, which is a Person type. I map this as an FNH "Reference".
  • I have a BillableTime class which contains a property Person, which is a Person type. I map this as an FNH "Reference".
  • Person contains a collection (IList) of ExpenseReport types (property ExpenseReports)
  • Person contains a collection (IList) of BilledTime types (property Time)

(See classes and mappings at bottom of post.)

All was cool until I added the IList<BilledTime> Time collection to Person. Now, when I try to access _person.Time, I get an exception:

The code:

// 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();
}

The exception:

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=?]

It's true that BillingManager_id is an invalid column name, it doesn't exist in the BillableTime table. However, I don't understand why NHB has created this SQL... doesn't make sense to me. I have seen this "Invalid column name" exception a lot when searching for a solution, but nothing seems to work. Even more confusing: like BilledTime, the ExpenseReport type also contains a reference to Person and it works perfectly.

One thing I was able to figure out is that if I remove the BillingManager reference from the Person mapping (References(p => p.BillingManager)), the exception goes away and things seem to work (with respect to BillableTime; it of course breaks the BillingManager persistence). Now it seems like there is some "self-reference" problem, since the Person.BillingManager property is itself a reference to a Person.

Any idea what is going on here? I'm at a loss...

Thanks.

=== Classes & Mappings ===

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; }             
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

把人绕傻吧 2024-12-15 20:26:04

以下行应该可以解决问题,但我不知道为什么会发生这种情况。如果我有空闲时间我会调查一下。

HasMany(p => p.Time).Cascade.AllDeleteOrphan().KeyColumn("Person_Id");

the following line should solve the issue, but i' dont know exactly why it is happening. if i have the spare time i will investigate.

HasMany(p => p.Time).Cascade.AllDeleteOrphan().KeyColumn("Person_Id");
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文