Skip to content

Commit d212c6b

Browse files
committed
NH-3413 - Linq - use original expression and parameters after getting QueryExpression from cache
1 parent afe1582 commit d212c6b

File tree

4 files changed

+52
-9
lines changed

4 files changed

+52
-9
lines changed

src/NHibernate.Test/Linq/WhereTests.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
using System;
2+
using System.Collections;
23
using System.Collections.Generic;
4+
using System.Collections.ObjectModel;
35
using System.Linq;
46
using System.Linq.Expressions;
7+
using NHibernate.Engine.Query;
58
using NHibernate.Linq;
69
using NHibernate.DomainModel.Northwind.Entities;
710
using NUnit.Framework;
@@ -415,6 +418,34 @@ where names.Contains(user.Name)
415418
Assert.AreEqual(2, query.Count);
416419
}
417420

421+
[Test, Description("NH-3413")]
422+
public void UsersWithListContains_MutatingListDoesNotBreakOtherSessions()
423+
{
424+
{
425+
var names = new List<string> { "ayende", "rahien" };
426+
427+
var query = (from user in db.Users
428+
where names.Contains(user.Name)
429+
select user).ToList();
430+
431+
Assert.AreEqual(2, query.Count);
432+
433+
names.Clear();
434+
}
435+
436+
{
437+
var names = new List<string> { "ayende" };
438+
439+
var query = (from user in db.Users
440+
where names.Contains(user.Name)
441+
select user).ToList();
442+
443+
// This line fails with Expected: 1 But was: 0
444+
// The SQL in NHProf shows that the where clause was executed as WHERE 1 = 0 as if names were empty
445+
Assert.AreEqual(1, query.Count);
446+
}
447+
}
448+
418449
[Test]
419450
public void UsersWithEmptyList_NH2400()
420451
{

src/NHibernate/Engine/Query/QueryPlanCache.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Iesi.Collections.Generic;
44

55
using NHibernate.Engine.Query.Sql;
6+
using NHibernate.Linq;
67
using NHibernate.Util;
78

89
namespace NHibernate.Engine.Query
@@ -94,6 +95,16 @@ public IQueryExpressionPlan GetHQLQueryPlan(IQueryExpression queryExpression, bo
9495
{
9596
log.Debug("located HQL query plan in cache (" + expressionStr + ")");
9697
}
98+
var planExpression = plan.QueryExpression as NhLinqExpression;
99+
var expression = queryExpression as NhLinqExpression;
100+
if (planExpression != null && expression != null)
101+
{
102+
//NH-3413
103+
//Here we have to use original expression.
104+
//TODO: cache only required parts of QueryExpression
105+
planExpression._expression = expression._expression;
106+
planExpression._constantToParameterMap = expression._constantToParameterMap;
107+
}
97108
}
98109

99110
return plan;

src/NHibernate/Impl/ExpressionQueryImpl.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,17 +109,18 @@ protected internal IQueryExpression ExpandParameters(IDictionary<string, TypedVa
109109
map.Add(name, aliases);
110110
}
111111

112+
//TODO: Do we need to translate expression one more time here?
112113
IASTNode newTree = ParameterExpander.Expand(QueryExpression.Translate(Session.Factory), map);
113114
var key = new StringBuilder(QueryExpression.Key);
114115

115116
map.Aggregate(key, (sb, kvp) =>
116-
{
117-
sb.Append(' ');
118-
sb.Append(kvp.Key);
119-
sb.Append(':');
120-
kvp.Value.Aggregate(sb, (sb2, str) => sb2.Append(str));
121-
return sb;
122-
});
117+
{
118+
sb.Append(' ');
119+
sb.Append(kvp.Key);
120+
sb.Append(':');
121+
kvp.Value.Aggregate(sb, (sb2, str) => sb2.Append(str));
122+
return sb;
123+
});
123124

124125
return new ExpandedQueryExpression(QueryExpression, newTree, key.ToString());
125126
}

src/NHibernate/Linq/NhLinqExpression.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ public class NhLinqExpression : IQueryExpression
2424

2525
public ExpressionToHqlTranslationResults ExpressionToHqlTranslationResults { get; private set; }
2626

27-
private readonly Expression _expression;
28-
private readonly IDictionary<ConstantExpression, NamedParameter> _constantToParameterMap;
27+
internal Expression _expression;
28+
internal IDictionary<ConstantExpression, NamedParameter> _constantToParameterMap;
2929

3030
public NhLinqExpression(Expression expression, ISessionFactory sessionFactory)
3131
{

0 commit comments

Comments
 (0)