|
我遇到了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("RowId"));+ z' ~+ `8 e$ b! i' O: D
Property(x => x.IdentID, map => map.Column("IdentID"));$ n$ k, E) j% \* B& |& r0 d; R
Property(x => x.Portfolio, map => map.Column("ortfolio"));
% m0 M% l+ a. v) w Property(x => x.ProfitCentre, map => map.Column("rofitCentre"));5 G6 \* w+ z$ z& d3 e, G, |
Property(x => x.MaturityDate, map => map.Column("Con_Expiry"));! c; z7 l- `' P2 _+ h+ r. J; L
Property(x => x.BuySell, map => map.Column("BS"));7 \9 I) h; h' O( q3 a
Property(x => x.Curr1, map => map.Column("Curr1"));1 Z8 J {( [ d# E' j3 z6 R
Property(x => x.Curr2, map => map.Column("Curr2"));# c% ~( R" m. @
Property(x => x.Reval, map => map.Column("Reval"));6 o( Q5 Y8 h$ H
Property(x => x.ContractType, map => map.Column("ContractType"));
5 S( p# u A+ T9 h- Q# J Property(x => x.ContractType2, map => map.Column("ContractType2"));9 A, r' Z+ m! U* X0 a
Property(x => x.ContractCode, map => map.Column("ContractCode"));
: G0 \; n" @& f$ p0 M( ?' _* q Property(x => x.AmountSignedTradeUnit, map => map.Column("AmountSignedTradeUnit"));
2 K$ D3 V9 T% `) r; e Property(x => x.Amount2Signed, map => map.Column("Amount2Signed"));
. ?& t% M- N8 {6 F8 m( W Property(x => x.ValSpot, map => map.Column("Val_Spot"));
- M$ t% d6 F$ v6 b9 ~; o6 O& R- V Property(x => x.SpotDelta, map => map.Column("SpotDelta"));
+ I' o r, K+ H- W4 t* J Property(x => x.TradeRevalCurr, map => map.Column("Traderevalcurr"));
: d& k `% y% y7 { Property(x => x.SourceReport, map => map.Column("SourceReport"));
9 A! o! E& X0 M1 A ManyToOne(x => x.RunContext, map => map.Column("RunContextID"));9 U+ ]/ [+ p, ]2 }, p
Table("Staging.vw_Liquidity");/ 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("BusinessBreakdownStandardPositionID");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 = "dbo.HiValue",
$ [0 N1 T, F4 \! T0 ^+ D4 a max_lo = 10000,* A. t$ C3 d4 A9 p4 J" w
Where = string.Format("EntityName = 'BusinessBreakdownStandardPosition'")
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("FinalNettingAmountUSD"));
- P3 d4 N3 @; L# Y8 R ~! Z4 w; V Property(x => x.InitialChargeAmountUSD, map => map.Column("InitialAmountUSD"));# 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("ReportRunContextID"));
! 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("InitialPrrID");! 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("Reporting.BusinessBreakdownFinalInstrumentPositionStandardPositionMap");6 G! M8 _! r8 Y% N1 ]' q
collectionMapping.Cascade(Cascade.All);
3 _/ {& ~1 a: Y5 s( D( P ? collectionMapping.Key(k => k.Column("StandardPositionID"));/ ^8 Y' R- _, i) r
}, mapping => mapping.ManyToMany(y => y.Column("FinalInstrumentPositionID")));
1 L2 C! E; r' v. @ Table("Reporting.BusinessBreakdownStandardPosition");# ^+ 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网上论坛以获取问题的完整详细信息。 |
|