在我的项目中,我使用 NHibernate/FluentNHibernate,并且我正在使用两个实体,契约(Contract)和服务。
这是我的契约(Contract)类型:
[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
}
好的,如您所见,我希望我的契约(Contract)对象有很多服务,并且每个服务都需要对父契约(Contract)有一个引用。
我正在使用 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");
}
我的问题来了:如果我检索数据库中所有契约(Contract)的列表,它就可以工作。如果我检索给定契约(Contract)中所有服务的列表,我会得到一个 StackOverflowException....
你觉得我写的有什么问题吗?
我犯了什么错误吗?
如果您需要任何其他信息,请告诉我。
哦,是的,我没说……查看堆栈跟踪,我看到系统正在加载所有服务,然后再次加载与这些服务相关的契约(Contract)。
我真的没有必要的经验或想法来了解正在发生的事情..所以任何帮助都会非常棒!
提前致谢,
干杯,
詹卢卡。
最佳答案
事实证明,这两个类(TTLCContract 和 TTLCService)都有一个自定义的 GetHashCode() 函数。
好吧,我几乎羞于继续解释......
TTLCContract 的 GetHashCode() 正在调用它自己的字段的 GetHashCode - 这是正确的。虽然,这些字段之一是“服务”,因此存在诸如 Service.GetHashCode() 之类的调用。后一个函数是按照相同的原则构建的:它在其每个内部字段上调用 GetHashCode() 函数。其中之一是契约(Contract)。
因此,Contract.GetHashCode() 正在调用 Service.GetHashCode(),而 Service.GetHashCode() 正在调用 Contract.GetHashCode()。这个循环是 StackOverflowException 的原因。
实际上,情况比我刚才描述的要复杂一些:Contract 和 Service 确实有很多子对象,而且我在其中的许多子对象上都遇到了同样的问题。
我们的测试套件现在已经被重写以针对这些可能性进行测试。
关于nhibernate/fluenthibernate 抛出 StackOverflowException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2867715/