Sql NHibernate-查询中的列错误

Sql NHibernate-查询中的列错误,sql,nhibernate,nhibernate-mapping,nhibernate-criteria,Sql,Nhibernate,Nhibernate Mapping,Nhibernate Criteria,我在NHibernate中遇到了一个间歇问题,它为一个实体生成一个查询,但用一个来自完全不同(且不相关)实体的列替换其中一个列 它只替换单个列,通常通过重新启动应用程序来解决(尽管有时需要几次尝试) ASP.NET应用程序(.NET 4.0) 在应用程序启动期间创建的SessionFactory NHibernate 3.3.1-通过代码映射完成的所有映射/配置 使用Nhibernate标准 如果您对此有任何意见,我们将不胜感激 实体 public class LiquiditySource

我在NHibernate中遇到了一个间歇问题,它为一个实体生成一个查询,但用一个来自完全不同(且不相关)实体的列替换其中一个列

它只替换单个列,通常通过重新启动应用程序来解决(尽管有时需要几次尝试)

  • ASP.NET应用程序(.NET 4.0)
  • 在应用程序启动期间创建的SessionFactory
  • NHibernate 3.3.1-通过代码映射完成的所有映射/配置
  • 使用Nhibernate标准
如果您对此有任何意见,我们将不胜感激

实体

public class LiquiditySourceItem : RunDataEntity, IEntity<int>
    {
        public virtual int Id { get; protected internal set; }
        public virtual int IdentID { get; protected internal set; }
        public virtual string Portfolio { get; protected internal set; }
        public virtual string ProfitCentre { get; protected internal set; }
        public virtual DateTime? MaturityDate { get; protected internal set; }
        public virtual string Curr1 { get; protected internal set; }
        public virtual string Curr2 { get; protected internal set; }
        public virtual decimal Reval { get; protected internal set; }
        public virtual string ContractType { get; protected internal set; }
        public virtual string ContractType2 { get; protected internal set; }
        public virtual string ContractCode { get; protected internal set; }
        public virtual decimal AmountSignedTradeUnit { get; protected internal set; }
        public virtual decimal Amount2Signed { get; protected internal set; }
        public virtual decimal SpotDelta { get; protected internal set; }
        public virtual string TradeRevalCurr { get; protected internal set; }
    }
public class BusinessBreakdownStandardPosition : ReportRunDataEntity, IEntity<long>
    {
        public virtual long Id { get; set; }
        public virtual decimal FinalNettingAmountUSD { get; set; }
        public virtual decimal InitialChargeAmountUSD { get; set; }
        public virtual BusinessBreakdownInitialPrr InitialPrr { get; set; }
        public virtual IEnumerable<FinalInstrumentPosition> FinalInstrumentPositions { get; set; }
        public virtual decimal CreditEventPaymentUSD { get; set; }
        public virtual decimal ValuationChangeIncreaseUSD { get; set; }
        public virtual decimal ValuationChangeDecreaseUSD { get; set; }
        public virtual string ReportKey { get; set; }
        public virtual decimal USDCharge { get; set; }
        public virtual decimal USDChargeICG { get; set; }
        public virtual string InstrumentType { get; set; } 
}
报告实体

public class LiquiditySourceItem : RunDataEntity, IEntity<int>
    {
        public virtual int Id { get; protected internal set; }
        public virtual int IdentID { get; protected internal set; }
        public virtual string Portfolio { get; protected internal set; }
        public virtual string ProfitCentre { get; protected internal set; }
        public virtual DateTime? MaturityDate { get; protected internal set; }
        public virtual string Curr1 { get; protected internal set; }
        public virtual string Curr2 { get; protected internal set; }
        public virtual decimal Reval { get; protected internal set; }
        public virtual string ContractType { get; protected internal set; }
        public virtual string ContractType2 { get; protected internal set; }
        public virtual string ContractCode { get; protected internal set; }
        public virtual decimal AmountSignedTradeUnit { get; protected internal set; }
        public virtual decimal Amount2Signed { get; protected internal set; }
        public virtual decimal SpotDelta { get; protected internal set; }
        public virtual string TradeRevalCurr { get; protected internal set; }
    }
public class BusinessBreakdownStandardPosition : ReportRunDataEntity, IEntity<long>
    {
        public virtual long Id { get; set; }
        public virtual decimal FinalNettingAmountUSD { get; set; }
        public virtual decimal InitialChargeAmountUSD { get; set; }
        public virtual BusinessBreakdownInitialPrr InitialPrr { get; set; }
        public virtual IEnumerable<FinalInstrumentPosition> FinalInstrumentPositions { get; set; }
        public virtual decimal CreditEventPaymentUSD { get; set; }
        public virtual decimal ValuationChangeIncreaseUSD { get; set; }
        public virtual decimal ValuationChangeDecreaseUSD { get; set; }
        public virtual string ReportKey { get; set; }
        public virtual decimal USDCharge { get; set; }
        public virtual decimal USDChargeICG { get; set; }
        public virtual string InstrumentType { get; set; } 
}
例外情况

System.Data.SqlClient.SqlException (0x80131904): Invalid column name 'InitialAmountUSD'.
如您所见,nhibernate已将LiquiditySourceItem列“Traderevalcurr”替换为“InitialAmountUSD”,它属于BusinessBreakdownStandardPosition实体。这些实体没有任何关系。否则,SQL与您期望的完全一样(包括列顺序)

观察结果

  • 错误列始终是其他映射实体中的有效列
  • 错误的列将替换现有列
  • 这个问题有时发生在其他实体之间。同样,这两者之间没有关系

有什么想法吗?

我在NHibernate用户谷歌群组论坛上问了同样的问题,有人认为他们已经找到了根本原因(并提出了解决方案):

问题代码位于PropertyPath.Equals(PropertyPath)中,它试图仅使用哈希代码来确定相等性。对于较小的代码基,这可以作为默认对象使用。GetHashCode()返回一个顺序对象索引。但是,在垃圾收集之后,这些索引会被重用,因为最终确定的对象会被删除并创建新对象…这会导致多个对象获得相同的哈希代码…一旦垃圾收集开始,属性路径有机会共享相同的哈希代码,这意味着它们最终会将冲突属性的自定义项混合在一起,从而导致错误的列名

如果要修复此错误,可以修补NH源代码:

如果您有自己的NH源代码副本,您可以通过更改NHibernate/Mapping/ByCode/PropertyPath.cs行#66来修复此错误,方法是:

返回hashCode==other.GetHashCode()

致:

返回hashCode==other.GetHashCode()&&ToString()==other.ToString()


请查看谷歌集团了解该问题的详细信息。

这个问题是否总是影响相同的实体和列,或者这是一个普遍存在的问题?如果是前者,我希望在某个地方会有一些随机的错误配置……至少还有一个实体发生了这种情况。同样,它是间歇性的,我还没有能够始终如一地重现问题。它还影响到我上面提到的两个实体,也就是说,有时它会将“LiquiditySourceItem”中的一列替换为“BusinessBreakdownStandardPosition”中的另一列,有时反过来,代码映射是否允许生成hbm.xml文件?如果是这样,请检查这些文件以验证映射。您是否在环境中或更可能在解决方案中查找了随机的.hbm.xml文件?
System.Data.SqlClient.SqlException (0x80131904): Invalid column name 'InitialAmountUSD'.