nhibernate/fluidhibernate 抛出 StackOverflowException
在我的项目中,我使用 NHibernate/FluentNHibernate,并且我正在使用两个实体:合约和服务。
这是我的合同类型:
[Serializable]
public partial class TTLCContract
{
public virtual long? Id { get; set; }
// other properties here
public virtual Iesi.Collections.Generic.ISet<TTLCService> Services { get; set; }
// implementation of Equals
// and GetHashCode here
}
这是我的服务类型:
[Serializable]
public partial class TTLCService
{
public virtual long? Id { get; set; }
// other properties here
public virtual Activity.Models.TTLCContract Contract { get; set; }
// implementation of Equals
// and GetHashCode here
}
好的,正如您所看到的,我希望我的合同对象具有许多服务,并且每个服务都需要有对父合同的引用。
我正在使用 FluentNhibernate。所以我的映射文件如下:
public TTLCContractMapping()
{
Table("tab_tlc_contracts");
Id(x => x.Id, "tlc_contract_id");
HasMany(x => x.Services)
.Inverse()
.Cascade.All()
.KeyColumn("tlc_contract_id")
.AsSet();
}
我的问题来
public TTLCServiceMapping()
{
Table("tab_tlc_services");
Id(x => x.Id, "tlc_service_id");
References(x => x.Contract)
.Not.Nullable()
.Column("tlc_contract_id");
}
了:如果我检索数据库中所有合约的列表,它就可以工作。如果我检索给定合约中所有服务的列表,我会收到 StackOverflowException...
您发现我写的内容有什么问题吗? 我有什么错误吗?
如果您需要任何其他信息,请告诉我。
哦,是的,我错过了……查看堆栈跟踪,我看到系统正在加载所有服务,然后再次加载与这些服务相关的合同。
我真的没有必要的经验或想法来了解正在发生的事情..所以任何帮助都会非常非常好!
提前致谢, 干杯, 吉安卢卡.
In my project I am using NHibernate/FluentNHibernate, and I am working with two entities, contracts and services.
This is my contract type:
[Serializable]
public partial class TTLCContract
{
public virtual long? Id { get; set; }
// other properties here
public virtual Iesi.Collections.Generic.ISet<TTLCService> Services { get; set; }
// implementation of Equals
// and GetHashCode here
}
and this is my service type:
[Serializable]
public partial class TTLCService
{
public virtual long? Id { get; set; }
// other properties here
public virtual Activity.Models.TTLCContract Contract { get; set; }
// implementation of Equals
// and GetHashCode here
}
Ok, so as you can see, I want my contract object to have many services, and each Service needs to have a reference to the parent Contract.
I am using FluentNhibernate. So my mappings file are the following:
public TTLCContractMapping()
{
Table("tab_tlc_contracts");
Id(x => x.Id, "tlc_contract_id");
HasMany(x => x.Services)
.Inverse()
.Cascade.All()
.KeyColumn("tlc_contract_id")
.AsSet();
}
and
public TTLCServiceMapping()
{
Table("tab_tlc_services");
Id(x => x.Id, "tlc_service_id");
References(x => x.Contract)
.Not.Nullable()
.Column("tlc_contract_id");
}
and here comes my problem: if I retrieve the list of all contracts in the db, it works. if I retrieve the list of all services in a given contract, I get a StackOverflowException....
Do you see anything wrong with what I wrote?
Have I made any mistake?
Please let me know if you need any additional information.
Oh yes, I missed to say... looking at the stacktrace I see the system is loading all the services and then it is loading again the contracts related to those services.
I don't really have the necessary experience nor ideas anymore to understand what's going on.. so any help would be really really great!
Thanks in advance,
Cheers,
Gianluca.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
事实证明,这两个类(TTLCContract 和 TTLCService)都有一个自定义的 GetHashCode() 函数。
好吧,我几乎羞于继续解释……
TTLCContract 的 GetHashCode() 正在调用它自己的字段的 GetHashCode - 这是正确的。虽然这些字段之一是“Service”,因此存在诸如 Service.GetHashCode() 之类的调用。后一个函数是按照相同的原则构建的:它在其每个内部字段上调用 GetHashCode() 函数。其中之一就是合同。
因此,Contract.GetHashCode() 正在调用 Service.GetHashCode(),而 Service.GetHashCode() 正在调用 Contract.GetHashCode()。此循环是 StackOverflowException 的原因。
实际上,情况比我刚才描述的更复杂:Contract 和 Service 确实有很多子对象,而且我在其中许多子对象上遇到了同样的问题。
我们的测试套件现在已经被重写,以针对这些可能性进行测试。
It turns out that both the classes (TTLCContract & TTLCService) have a customized GetHashCode() function.
Well, I feel almost ashamed to carry on with the explanation...
TTLCContract's GetHashCode() was calling the GetHashCode of its own fields - and that's right. Although, one of these fields was "Service", hence there was a call such as Service.GetHashCode(). This latter function had been built following the same principle: it was calling the GetHashCode() function on each one of its internal fields. And one of these is Contract.
So, Contract.GetHashCode() was calling Service.GetHashCode() and Service.GetHashCode() was invoking Contract.GetHashCode(). This loop was the reason of the StackOverflowException.
Actually, the situation was kind of more complex than the one I have just described: Contract and Service have many child objects indeed, and I had the same problem on many of them.
Our test suite has now been rewritten to test against these eventualities too.
看来您可能会发生循环引用。我的意思是你加载服务,反过来加载合约,然后加载服务,然后我们再次开始...
我不确定流畅的 nhibernate 语法,但查看服务和合约的延迟加载,这样你就不会得不到这种级联效应。
It looks as though you may have a circular reference happening. by that I mean you load the services which inturn loads the contracts which then load the services and round we go again...
I am not sure of the fluent nhibernate syntax but look in to lazy loading of both services and contracts so that you don't get this cascade effect.