微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

sql – NHibernate – 错误的查询列

我在NHibernate中遇到一个间歇性的问题,它会为一个实体生成一个查询,而是用一个完全不同(和不相关)实体的列替换一个列.

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

> ASP.NET应用程序(.NET 4.0)
>在Application_Start中创建的SessionFactory
> NHibernate 3.3.1-通过Mapping By Code完成的所有映射/配置
>使用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 LiquiditySourceItemmap()
{
    Id(x => x.Id,map => map.Column("RowId"));
    Property(x => x.IdentID,map => map.Column("IdentID"));
    Property(x => x.Portfolio,map => map.Column("Portfolio"));
    Property(x => x.ProfitCentre,map => map.Column("ProfitCentre"));
    Property(x => x.maturityDate,map => map.Column("Con_Expiry"));
    Property(x => x.BuySell,map => map.Column("BS"));
    Property(x => x.Curr1,map => map.Column("Curr1"));
    Property(x => x.Curr2,map => map.Column("Curr2"));
    Property(x => x.Reval,map => map.Column("Reval"));
    Property(x => x.ContractType,map => map.Column("ContractType"));
    Property(x => x.ContractType2,map => map.Column("ContractType2"));
    Property(x => x.ContractCode,map => map.Column("ContractCode"));
    Property(x => x.AmountSignedTradeUnit,map => map.Column("AmountSignedTradeUnit"));
    Property(x => x.Amount2Signed,map => map.Column("Amount2Signed"));
    Property(x => x.ValSpot,map => map.Column("Val_Spot"));
    Property(x => x.SpotDelta,map => map.Column("SpotDelta"));
    Property(x => x.TradeRevalCurr,map => map.Column("Traderevalcurr"));
    Property(x => x.sourceReport,map => map.Column("SourceReport"));
    ManyToOne(x => x.runcontext,map => map.Column("runcontextID"));
    Table("Staging.vw_Liquidity");
}

报告实体

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 BusinessBreakdownStandardPositionMap : ClassMapping<BusinessBreakdownStandardPosition>
    {
        public BusinessBreakdownStandardPositionMap()
        {
            Id(x => x.Id,m =>
                   {
                       m.Column("BusinessBreakdownStandardPositionID");
                       m.Generator(Generators.HighLow,g =>
                                   g.Params(
                                       new
                                           {
                                               table = "dbo.HiValue",max_lo = 10000,Where = string.Format("EntityName = 'BusinessBreakdownStandardPosition'")
                                           }));
                   });
            Property(x => x.FinalNettingAmountUSD,map => map.Column("FinalNettingAmountUSD"));
            Property(x => x.InitialChargeAmountUSD,map => map.Column("InitialAmountUSD"));
            Property(x => x.CreditEventPaymentUSD);
            Property(x => x.ValuationChangeDecreaseUSD);
            Property(x => x.ValuationChangeIncreaseUSD);
            Property(x => x.USDCharge);
            Property(x => x.USDChargeICG);
            Property(x=>x.InstrumentType);
            ManyToOne(p => p.runcontext,map => map.Column("ReportruncontextID"));
            ManyToOne(p => p.InitialPrr,m =>
                {
                    m.Column("InitialPrrID");
                    m.Cascade(Cascade.All);
                });
            Property(x => x.ReportKey);
            Bag(x => x.FinalInstrumentPositions,collectionMapping =>
                {
                    collectionMapping.Table("Reporting.BusinessBreakdownFinalInstrumentPositionStandardPositionMap");
                    collectionMapping.Cascade(Cascade.All);
                    collectionMapping.Key(k => k.Column("StandardPositionID"));
                },mapping => mapping.ManyToMany(y => y.Column("FinalInstrumentPositionID")));
            Table("Reporting.BusinessBreakdownStandardPosition");
        }
    }

SQL查询,由NHibernate生成

SELECT
    this_.RowId AS RowId47_0_,this_.IdentID AS IdentID47_0_,this_.Portfolio AS Portfolio47_0_,this_.ProfitCentre AS ProfitCe4_47_0_,this_.Con_Expiry AS Con5_47_0_,this_.BS AS BS47_0_,this_.Curr1 AS Curr7_47_0_,this_.Curr2 AS Curr8_47_0_,this_.Reval AS Reval47_0_,this_.ContractType AS Contrac10_47_0_,this_.ContractType2 AS Contrac11_47_0_,this_.ContractCode AS Contrac12_47_0_,this_.AmountSignedTradeUnit AS AmountS13_47_0_,this_.Amount2Signed AS Amount14_47_0_,this_.Val_Spot AS Val15_47_0_,this_.SpotDelta AS SpotDelta47_0_,this_.InitialAmountUSD AS Initial17_47_0_,this_.runcontextID AS runcont18_47_0_,this_.sourceReport AS Sou19_47_0_
FROM Staging.vw_Liquidity this_

例外

System.Data.sqlClient.sqlException (0x80131904): Invalid column name 'InitialAmountUSD'.

你可以看到,nhibernate已经用“InitialAmountUSD”替换了LiquiditySourceItem列“Traderevalcurr”,它属于BusinessBreakdownStandardPosition实体.这些实体没有任何关系.否则,sql完全符合您的期望(包括列顺序).

意见

>错误的列始终是不同映射实体中的有效列
>错误的列将替换现有列
>这个问题有时候会在其他实体之间出现.再次,这些之间没有关系

有什么想法吗?

解决方法

我在NHibernate Users Google Groups论坛上提出了同样的问题,有人认为他们已经制定了根本原因(并提出了一个解决方案):

https://groups.google.com/forum/#!topic/nhusers/BZoBoyWQEvs

The problem code is in PropertyPath.Equals(PropertyPath) which attempts to determine equality by only using the hash code. This works fine for smaller code bases as the default Object.GetHashCode() returns a sequential object index. However,after garbage collection,these indices get reused as finalized objects are removed and new objects are created…which results in more than one object getting the same hashcode…Once garbage collection kicks in,property paths have a chance to share the same hashcode which means they will ultimately mix up their customizers for the colliding properties,thus the wrong column names…

如果你想修复这个错误,你可以修补NH源代码

If you have your own copy of the NH source,you can fix the bug by changing NHibernate/Mapping/ByCode/PropertyPath.cs line #66 from:

return hashCode == other.GetHashCode();

To:

return hashCode == other.GetHashCode() && ToString() == other.ToString();

有关问题的详细信息,请查看Google群组.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐