Skip to content

Commit 3317da4

Browse files
committed
Fix for NH-3436
1 parent e72502c commit 3317da4

File tree

4 files changed

+37
-4
lines changed

4 files changed

+37
-4
lines changed

src/NHibernate/Engine/Query/HQLExpressionQueryPlan.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,17 @@ public IQueryExpression QueryExpression
1414
protected set;
1515
}
1616

17+
private HQLExpressionQueryPlan(HQLQueryPlan source, IQueryExpression newQueryExpression)
18+
: base(source)
19+
{
20+
QueryExpression = newQueryExpression;
21+
}
22+
23+
internal HQLExpressionQueryPlan Copy(IQueryExpression newExpression)
24+
{
25+
return new HQLExpressionQueryPlan(this, newExpression);
26+
}
27+
1728
public HQLExpressionQueryPlan(string expressionStr, IQueryExpression queryExpression, bool shallow,
1829
IDictionary<string, IFilter> enabledFilters, ISessionFactoryImplementor factory)
1930
: this(expressionStr, queryExpression, null, shallow, enabledFilters, factory)

src/NHibernate/Engine/Query/HQLQueryPlan.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
using NHibernate.Event;
77
using NHibernate.Hql;
8+
using NHibernate.Linq;
89
using NHibernate.Type;
910
using NHibernate.Util;
1011

@@ -43,6 +44,16 @@ protected HQLQueryPlan(string sourceQuery, IQueryTranslator[] translators)
4344
FinaliseQueryPlan();
4445
}
4546

47+
internal HQLQueryPlan(HQLQueryPlan source)
48+
{
49+
Translators = source.Translators;
50+
_sourceQuery = source._sourceQuery;
51+
QuerySpaces = source.QuerySpaces;
52+
ParameterMetadata = source.ParameterMetadata;
53+
ReturnMetadata = source.ReturnMetadata;
54+
SqlStrings = source.SqlStrings;
55+
}
56+
4657
public ISet<string> QuerySpaces
4758
{
4859
get;

src/NHibernate/Engine/Query/QueryPlanCache.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public IQueryExpressionPlan GetHQLQueryPlan(IQueryExpression queryExpression, bo
7878
string expressionStr = queryExpression.Key;
7979

8080
var key = new HQLQueryPlanKey(queryExpression, shallow, enabledFilters);
81-
var plan = (IQueryExpressionPlan)planCache[key];
81+
var plan = (HQLExpressionQueryPlan) planCache[key];
8282

8383
if (plan == null)
8484
{
@@ -105,8 +105,12 @@ public IQueryExpressionPlan GetHQLQueryPlan(IQueryExpression queryExpression, bo
105105
// for cases when we have list parameters in query, like @p1.Contains(...),
106106
// it does, and then it uses parameters from first try.
107107
//TODO: cache only required parts of QueryExpression
108-
planExpression._expression = expression._expression;
109-
planExpression._constantToParameterMap = expression._constantToParameterMap;
108+
109+
//NH-3436
110+
// We have to return new instance plan with it's own query expression
111+
// because other treads can override queryexpression of current plan during execution of query if we will use cached instance of plan
112+
expression.CopyExpressionTranslation(planExpression);
113+
plan = plan.Copy(expression);
110114
}
111115
}
112116

src/NHibernate/Linq/NhLinqExpression.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using System.Linq;
34
using System.Linq.Expressions;
45
using NHibernate.Engine;
@@ -70,5 +71,11 @@ public IASTNode Translate(ISessionFactoryImplementor sessionFactory)
7071

7172
return ExpressionToHqlTranslationResults.Statement.AstNode;
7273
}
74+
75+
internal void CopyExpressionTranslation(NhLinqExpression other)
76+
{
77+
ExpressionToHqlTranslationResults = other.ExpressionToHqlTranslationResults;
78+
ParameterDescriptors = other.ParameterDescriptors;
79+
}
7380
}
7481
}

0 commit comments

Comments
 (0)