回答

收藏

NHibernate-查询错误的列

技术问答 技术问答 270 人阅读 | 0 人回复 | 2023-09-14

我遇到了NHibernate的间歇性问题,该问题会为实体生成查询,但是用来自完全不同(且不相关)的实体的列替换了其中的一列。
, {* [7 u! M8 S4 V它只能替换单个列,通常可以通过重新启动应用程序来解决(尽管有时需要进行几次尝试)。
' U* K( U0 H/ Q  \ASP.NET应用程序(.NET 4.0)
8 y/ @& H8 c1 f8 O在Application_Start期间创建的SessionFactory
9 X. t) C+ ^3 k5 r4 `5 X3 ]' sNHibernate 3.3.1-通过代码映射完成所有映射/配置
' N! ~5 d  }, ]0 q使用Nhibernate条件
; p1 t; e; b( O% l

( G7 d: L9 w7 z, b任何输入对此将不胜感激!
$ ~' C: K1 E/ E6 x: {6 t  _实体1 N6 u( T: \" I* S
public class LiquiditySourceItem : RunDataEntity, IEntity<i>" d2 h/ W! T3 j  v3 x; \
    {8 B4 ?6 H" z0 g& Q/ z# j
        public virtual int Id { get; protected internal set; }+ `& e2 r6 s$ c% Z6 m& T4 r! C
        public virtual int IdentID { get; protected internal set; }* A2 `- D* B* E* T# g) _8 r
        public virtual string Portfolio { get; protected internal set; }6 q  N, [& ?% y# |
        public virtual string ProfitCentre { get; protected internal set; }5 e7 L' N2 c7 |8 V4 m
        public virtual DateTime? MaturityDate { get; protected internal set; }
) `/ c6 z% R$ e& E; g        public virtual string Curr1 { get; protected internal set; }
* o% y: b. ]! v  C. `- \. U        public virtual string Curr2 { get; protected internal set; }  U; i3 G- Z1 \1 u+ ]9 B6 v
        public virtual decimal Reval { get; protected internal set; }1 @* M: l1 A- R' L
        public virtual string ContractType { get; protected internal set; }
& i' u& p9 Q" z$ Q        public virtual string ContractType2 { get; protected internal set; }
1 k8 a* l$ d% _- u' _        public virtual string ContractCode { get; protected internal set; }
. p' X- n7 R, |5 s4 S  R( W        public virtual decimal AmountSignedTradeUnit { get; protected internal set; }
* G9 @1 a. R$ R: \1 C0 d: m' m        public virtual decimal Amount2Signed { get; protected internal set; }
7 w/ u/ o% ]$ |4 X        public virtual decimal SpotDelta { get; protected internal set; }. f9 z& p: U' p
        public virtual string TradeRevalCurr { get; protected internal set; }, _& s, i2 H1 D0 q* H  C
    }+ m% G% G$ \+ D7 V$ s, F# M2 E+ @
实体映射
2 `0 F* h& W) ?" H1 Fpublic LiquiditySourceItemMap()% E; l: P) v3 J6 r" l
{
) j$ A( D# q* `; I7 C3 a: _" G    Id(x => x.Id, map => map.Column(&quot;RowId&quot;));+ z' ~+ `8 e$ b! i' O: D
    Property(x => x.IdentID, map => map.Column(&quot;IdentID&quot;));$ n$ k, E) j% \* B& |& r0 d; R
    Property(x => x.Portfolio, map => map.Column(&quotortfolio&quot;));
% m0 M% l+ a. v) w    Property(x => x.ProfitCentre, map => map.Column(&quotrofitCentre&quot;));5 G6 \* w+ z$ z& d3 e, G, |
    Property(x => x.MaturityDate, map => map.Column(&quot;Con_Expiry&quot;));! c; z7 l- `' P2 _+ h+ r. J; L
    Property(x => x.BuySell, map => map.Column(&quot;BS&quot;));7 \9 I) h; h' O( q3 a
    Property(x => x.Curr1, map => map.Column(&quot;Curr1&quot;));1 Z8 J  {( [  d# E' j3 z6 R
    Property(x => x.Curr2, map => map.Column(&quot;Curr2&quot;));# c% ~( R" m. @
    Property(x => x.Reval, map => map.Column(&quot;Reval&quot;));6 o( Q5 Y8 h$ H
    Property(x => x.ContractType, map => map.Column(&quot;ContractType&quot;));
5 S( p# u  A+ T9 h- Q# J    Property(x => x.ContractType2, map => map.Column(&quot;ContractType2&quot;));9 A, r' Z+ m! U* X0 a
    Property(x => x.ContractCode, map => map.Column(&quot;ContractCode&quot;));
: G0 \; n" @& f$ p0 M( ?' _* q    Property(x => x.AmountSignedTradeUnit, map => map.Column(&quot;AmountSignedTradeUnit&quot;));
2 K$ D3 V9 T% `) r; e    Property(x => x.Amount2Signed, map => map.Column(&quot;Amount2Signed&quot;));
. ?& t% M- N8 {6 F8 m( W    Property(x => x.ValSpot, map => map.Column(&quot;Val_Spot&quot;));
- M$ t% d6 F$ v6 b9 ~; o6 O& R- V    Property(x => x.SpotDelta, map => map.Column(&quot;SpotDelta&quot;));
+ I' o  r, K+ H- W4 t* J    Property(x => x.TradeRevalCurr, map => map.Column(&quot;Traderevalcurr&quot;));
: d& k  `% y% y7 {    Property(x => x.SourceReport, map => map.Column(&quot;SourceReport&quot;));
9 A! o! E& X0 M1 A    ManyToOne(x => x.RunContext, map => map.Column(&quot;RunContextID&quot;));9 U+ ]/ [+ p, ]2 }, p
    Table(&quot;Staging.vw_Liquidity&quot;);/ a. {. e. [. w- b) H
}! \8 h0 ~& j( K& W
报告实体
/ L, o3 ]. `8 [- d+ |: M; E+ Hpublic class BusinessBreakdownStandardPosition : ReportRunDataEntity, IEntity
! Y0 }! ^! t7 z$ H    {
4 _. g$ Z: M  D0 b        public virtual long Id { get; set; }9 [- C7 S* ~5 X
        public virtual decimal FinalNettingAmountUSD { get; set; }
! k. x/ _& w: Z( G5 N        public virtual decimal InitialChargeAmountUSD { get; set; }
* e- m- p+ |% H5 f7 w9 ]3 r3 X        public virtual BusinessBreakdownInitialPrr InitialPrr { get; set; }  M6 |/ C/ a" _' y* j: M
        public virtual IEnumerable FinalInstrumentPositions { get; set; }4 ^: g3 ?7 j% |" T/ i' f/ Y
        public virtual decimal CreditEventPaymentUSD { get; set; }
" i0 \. X, T( Z        public virtual decimal ValuationChangeIncreaseUSD { get; set; }3 ?/ E" g) C* |" ]1 r. E
        public virtual decimal ValuationChangeDecreaseUSD { get; set; }+ R; t6 Q5 \% x* H* u; D1 x
        public virtual string ReportKey { get; set; }
- k. I" n; I* v: C& {        public virtual decimal USDCharge { get; set; }
# O" `8 L. \1 w* k+ g1 _0 G& [1 `        public virtual decimal USDChargeICG { get; set; }
, u6 _  U" w6 v, d' M        public virtual string InstrumentType { get; set; }
6 Y4 L$ ~% \, k$ }6 W$ j. a}
$ c- @% n) B8 A; ~# r$ q# |报告实体映射) R/ O5 W- R4 N0 e9 L" ]/ R
public class BusinessBreakdownStandardPositionMap : ClassMapping[B]8 P. I) U) L. K# T
    {
$ a' r) S- ^: P2 Z6 {        public BusinessBreakdownStandardPositionMap()
$ Z9 |& G% h5 G3 _, ]        {
, C# ~% j0 R: q' r0 [( e+ V+ Y& l            Id(x => x.Id,
; U# F, L* W! y- |* {$ K7 V               m =>
2 b& j# v4 t% R5 f                   {
7 @7 y) ~6 o7 Q                       m.Column(&quot;BusinessBreakdownStandardPositionID&quot;);5 ^$ M8 W( R1 _8 o9 w. s) @
                       m.Generator(Generators.HighLow,2 t# S* Q/ Q( _7 m' c
                                   g =>( w$ t# W& u( M. I) r2 B
                                   g.Params(# x: x1 L3 n0 W1 Q" G
                                       new
- z( S! T3 R3 T) C: W; O                                           {
- @( D! P( P) S3 X+ F) ?                                               table = &quot;dbo.HiValue&quot;,
$ [0 N1 T, F4 \! T0 ^+ D4 a                                               max_lo = 10000,* A. t$ C3 d4 A9 p4 J" w
                                               Where = string.Format(&quot;EntityName = 'BusinessBreakdownStandardPosition'&quot;)
2 e8 _+ z% D) p                                           }));- }9 e2 F+ c& B4 s7 t' Y& W+ C. \
                   });
0 |, [# {# g2 N! x* h# h4 ?& E            Property(x => x.FinalNettingAmountUSD, map => map.Column(&quot;FinalNettingAmountUSD&quot;));
- P3 d4 N3 @; L# Y8 R  ~! Z4 w; V            Property(x => x.InitialChargeAmountUSD, map => map.Column(&quot;InitialAmountUSD&quot;));# S' H+ K$ L- v
            Property(x => x.CreditEventPaymentUSD);) l! K8 M, }: v4 R
            Property(x => x.ValuationChangeDecreaseUSD);( v" A; q2 b6 _8 D; e3 \# b
            Property(x => x.ValuationChangeIncreaseUSD);
: K: ~9 V, F+ w  D/ b            Property(x => x.USDCharge);
' e  ?- R1 i) p# ~8 B            Property(x => x.USDChargeICG);
4 t3 m' M# J: D. l8 R            Property(x=>x.InstrumentType);/ y  w: y+ b! Z6 Q( c5 U
            ManyToOne(p => p.RunContext, map => map.Column(&quot;ReportRunContextID&quot;));
! B; {% y  r. U; x7 P            ManyToOne(p => p.InitialPrr, m =>" S. c, c  c; D* M
                {* g% q7 E! l" }+ m  Y$ N( }
                    m.Column(&quot;InitialPrrID&quot;);! H9 @& `5 @5 r: p/ G
                    m.Cascade(Cascade.All);8 u" P/ j/ I/ ^7 O" g, m) S
                });
2 J2 q" e  Q! l+ c# S; b2 V" A            Property(x => x.ReportKey);
" L+ K' l( \' {6 |            Bag(x => x.FinalInstrumentPositions, collectionMapping =>
8 r$ l1 O: j2 ^" b, m                {9 e/ T6 [" H) ?: Q, u6 |5 O
                    collectionMapping.Table(&quot;Reporting.BusinessBreakdownFinalInstrumentPositionStandardPositionMap&quot;);6 G! M8 _! r8 Y% N1 ]' q
                    collectionMapping.Cascade(Cascade.All);
3 _/ {& ~1 a: Y5 s( D( P  ?                    collectionMapping.Key(k => k.Column(&quot;StandardPositionID&quot;));/ ^8 Y' R- _, i) r
                }, mapping => mapping.ManyToMany(y => y.Column(&quot;FinalInstrumentPositionID&quot;)));
1 L2 C! E; r' v. @            Table(&quot;Reporting.BusinessBreakdownStandardPosition&quot;);# ^+ v6 v: r8 D
        }: S9 Z+ ^( v  i
    }+ U* _/ p/ w1 H& z* B% }  [
NHibernate生成的SQL查询; A& K5 M" u! k: S; y' Z
SELECT  Z: U+ m5 r. Q3 v2 D
    this_.RowId AS RowId47_0_,( P! @+ U+ @) W/ o7 l
    this_.IdentID AS IdentID47_0_,
1 i9 M( X' U6 V( q) N/ W    this_.Portfolio AS Portfolio47_0_,
" {3 [+ `& B7 v4 |9 A4 M    this_.ProfitCentre AS ProfitCe4_47_0_,* n1 e9 ~7 C1 }+ }
    this_.Con_Expiry AS Con5_47_0_,
' l0 F2 m7 F& J2 i: l    this_.BS AS BS47_0_,# z3 I1 ?4 u. Q0 @6 u/ \- m
    this_.Curr1 AS Curr7_47_0_,* c8 ], ?+ @5 Z3 i4 ^
    this_.Curr2 AS Curr8_47_0_,3 U7 y, `8 }4 n1 O' ]+ J/ C/ b( A
    this_.Reval AS Reval47_0_,; x# u; l  Q* K! x7 `6 y2 q. h: O
    this_.ContractType AS Contrac10_47_0_,, ]/ M- ?* \0 q" y8 p. D
    this_.ContractType2 AS Contrac11_47_0_,
' S4 F* [' q* S    this_.ContractCode AS Contrac12_47_0_,
) A7 J9 H, z  H" a    this_.AmountSignedTradeUnit AS AmountS13_47_0_,9 t* F; T4 f2 u- o
    this_.Amount2Signed AS Amount14_47_0_,
& W1 Y6 d$ x9 s- z* [+ @  ~( Y; |    this_.Val_Spot AS Val15_47_0_,
( r9 S3 H; I! l) i1 m; m& \( N! M    this_.SpotDelta AS SpotDelta47_0_,
8 ~* {/ `: E' @  C! }, ]3 k1 j    this_.InitialAmountUSD AS Initial17_47_0_,
3 o8 ~6 D) e* x. g. j4 P3 J    this_.RunContextID AS RunCont18_47_0_,# m: C7 _1 ^* p/ Q' S* J
    this_.SourceReport AS Sou19_47_0_
, T8 P, W: ]. S- c- X' Q, H% I* ~FROM Staging.vw_Liquidity this_
) T+ K2 B- ?7 P% B- X例外
8 z" `: Y* E" j* C8 rSystem.Data.SqlClient.SqlException (0x80131904): Invalid column name 'InitialAmountUSD'.5 s$ z' `% n) Q! w. r
如您所见,nhibernate已将LiquiditySourceItem列’Traderevalcurr’替换为’InitialAmountUSD’,该列属于BusinessBreakdownStandardPosition实体。这些实体没有任何关系。否则,SQL完全符合您的期望(包括列顺序)。" [! z2 U, I2 W6 @7 f8 b- y! B3 R2 }
观察结果! M" r2 X1 c5 U( x
错误的列始终是其他映射实体中的有效列
) q" J  N  d1 g错误的列将替换现有的列
. i# @* ^2 X* ~8 X1 k有时在其他实体之间也会发生此问题。同样,这些之间没有任何关系
+ a! |$ v* n5 L& x

% w) x" g1 V9 P. \# t, a3 w7 {有什么想法吗?
8 i6 r. V" _3 ^$ ^  B3 ?9 D$ k4 `% n( ~                8 q* F* w' K" C; A
解决方案:: d0 K( f$ e' X. ?
                : h4 ^) Y1 \! w7 l
' A* v  h4 H4 {  E# Z

5 }2 h/ q; R; [: H/ x                我在NHibernate用户Google网上论坛上问了同样的问题,有人认为他们已经找到了根本原因(并且还提出了解决方案):
. S% E: A& G$ ^5 `https://groups.google.com/forum/#!topic/nhusers/BZoBoyWQEvs
! m1 W2 c! [& E. ]8 B' d" Z" j/ C0 z4 E8 k4 e. ^
问题代码在PropertyPath.Equals(PropertyPath)中,该属性试图仅通过使用哈希码来确定相等性。这对于较小的代码库来说效果很好,因为默认的Object.GetHashCode()返回一个顺序的对象索引。但是,在垃圾回收之后,这些索引会在删除最终对象并创建新对象时重新使用…这导致多个对象获得相同的哈希码…一旦启动垃圾回收,属性路径就有机会共享相同的哈希码,这意味着它们最终将为冲突的属性混合其定制器,从而导致错误的列名…/ S/ f/ _2 c! s# g' V
7 M% u2 T8 a/ [5 P, _
如果要解决此错误,可以修补NH源代码:
* e" Y8 ^1 r' _/ A  _4 r+ X! f* J. b* U! z, O' l! R
如果您拥有自己的NH源副本,则可以通过将NHibernate / Mapping / ByCode /; B8 J. Z; g  J4 z( m
PropertyPath.cs第66行从以下位置更改来修复该错误:  t4 r  @' a8 V: `5 R2 h/ D
return hashCode == other.GetHashCode();: ?/ T6 E! ~. O6 y- m  k
到:
" N2 ]  a# j/ }8 [8 P8 C9 areturn hashCode == other.GetHashCode() && ToString() == other.ToString();
8 z3 r2 _  h$ b( n  o
/ }5 G, Z# s  p2 j% ~4 _3 l请查看Google网上论坛以获取问题的完整详细信息。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则