Skip to content

Commit 4983721

Browse files
committed
Merge branch '3.3.x' into master
2 parents c20f3ec + ba59abe commit 4983721

File tree

11 files changed

+305
-4
lines changed

11 files changed

+305
-4
lines changed

src/NHibernate.Test/Linq/LoggingTests.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Linq;
22
using NHibernate.Cfg;
3+
using NHibernate.DomainModel.Northwind.Entities;
34
using NUnit.Framework;
45

56
namespace NHibernate.Test.Linq
@@ -26,5 +27,35 @@ public void PageBetweenProjections()
2627
}
2728
}
2829

30+
31+
[Test]
32+
public void CanLogLinqExpressionWithoutInitializingContainedProxy()
33+
{
34+
var productId = db.Products.Select(p => p.ProductId).First();
35+
36+
using (var logspy = new LogSpy("NHibernate.Linq"))
37+
{
38+
var productProxy = session.Load<Product>(productId);
39+
Assert.That(NHibernateUtil.IsInitialized(productProxy), Is.False);
40+
41+
var result = from product in db.Products
42+
where product == productProxy
43+
select product;
44+
45+
Assert.That(result.Count(), Is.EqualTo(1));
46+
47+
// Verify that the expected logging did happen.
48+
var actualLog = logspy.GetWholeLog();
49+
50+
const string expectedLog =
51+
"Expression (partially evaluated): value(NHibernate.Linq.NhQueryable`1[NHibernate.DomainModel.Northwind.Entities.Product])" +
52+
".Where(product => (product == Product#1)).Count()";
53+
Assert.That(actualLog, Is.StringContaining(expectedLog));
54+
55+
// And verify that the proxy in the expression wasn't initialized.
56+
Assert.That(NHibernateUtil.IsInitialized(productProxy), Is.False,
57+
"ERROR: We expected the proxy to NOT be initialized.");
58+
}
59+
}
2960
}
3061
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System;
2+
3+
namespace NHibernate.Test.NHSpecificTest.NH3428
4+
{
5+
public class Entity
6+
{
7+
public virtual Guid Id { get; set; }
8+
public virtual string Name { get; set; }
9+
}
10+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
using NUnit.Framework;
2+
3+
namespace NHibernate.Test.NHSpecificTest.NH3428
4+
{
5+
using NHibernate.Criterion;
6+
7+
[TestFixture]
8+
public class Fixture : BugTestCase
9+
{
10+
11+
protected override bool AppliesTo(Dialect.Dialect dialect)
12+
{
13+
return dialect is Dialect.MsSql2005Dialect;
14+
}
15+
16+
protected override void OnSetUp()
17+
{
18+
using (ISession session = OpenSession())
19+
using (ITransaction transaction = session.BeginTransaction())
20+
{
21+
var e1 = new Entity { Name = "Bob" };
22+
session.Save(e1);
23+
24+
var e2 = new Entity { Name = "Sally" };
25+
session.Save(e2);
26+
27+
session.Flush();
28+
transaction.Commit();
29+
}
30+
}
31+
32+
protected override void OnTearDown()
33+
{
34+
using (ISession session = OpenSession())
35+
using (ITransaction transaction = session.BeginTransaction())
36+
{
37+
session.Delete("from System.Object");
38+
39+
session.Flush();
40+
transaction.Commit();
41+
}
42+
}
43+
44+
[Test]
45+
public void QueryFailsWhenDistinctOrderedResultIsPagedPastPageOne()
46+
{
47+
using (ISession session = this.OpenSession())
48+
using (session.BeginTransaction())
49+
{
50+
var criteria = session.CreateCriteria<Entity>();
51+
var projectionList = Projections.ProjectionList().Add(Projections.Property("Name"), "Name");
52+
53+
criteria.SetProjection(Projections.Distinct(projectionList));
54+
55+
criteria.SetFirstResult(1).SetMaxResults(1);
56+
criteria.AddOrder(Order.Asc("Name"));
57+
58+
var result = criteria.List();
59+
60+
Assert.AreEqual(1, result.Count);
61+
Assert.AreEqual("Sally", result[0]);
62+
}
63+
}
64+
}
65+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernate.Test" namespace="NHibernate.Test.NHSpecificTest.NH3428">
3+
4+
<class name="Entity">
5+
<id name="Id" generator="guid.comb" />
6+
<property name="Name" />
7+
</class>
8+
</hibernate-mapping>
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Threading;
5+
using NHibernate.Cfg.MappingSchema;
6+
using NHibernate.Linq;
7+
using NHibernate.Mapping.ByCode;
8+
using NUnit.Framework;
9+
10+
namespace NHibernate.Test.NHSpecificTest.NH3436
11+
{
12+
public class Fixture : TestCaseMappingByCode
13+
{
14+
protected override HbmMapping GetMappings()
15+
{
16+
var mapper = new ModelMapper();
17+
mapper.Class<TestEntity>(rc =>
18+
{
19+
rc.Table("TestEntity");
20+
rc.Id(x => x.Id, m => m.Generator(Generators.GuidComb));
21+
});
22+
return mapper.CompileMappingForAllExplicitlyAddedEntities();
23+
}
24+
25+
protected override void OnSetUp()
26+
{
27+
using (var session = OpenSession())
28+
using (var transaction = session.BeginTransaction())
29+
{
30+
var e1 = new TestEntity();
31+
session.Save(e1);
32+
33+
var e2 = new TestEntity();
34+
session.Save(e2);
35+
36+
session.Flush();
37+
transaction.Commit();
38+
}
39+
}
40+
41+
protected override void OnTearDown()
42+
{
43+
using (var session = OpenSession())
44+
using (var transaction = session.BeginTransaction())
45+
{
46+
session.Delete("from System.Object");
47+
48+
session.Flush();
49+
transaction.Commit();
50+
}
51+
}
52+
53+
[Test]
54+
public void TestQueryWithContainsInParallel()
55+
{
56+
var ids = new List<Guid>
57+
{
58+
Guid.NewGuid(),
59+
Guid.NewGuid(),
60+
};
61+
const int threadsToRun = 32;
62+
var events = new WaitHandle[threadsToRun];
63+
var exceptions = new List<Exception>();
64+
for (var i = 0; i < threadsToRun; i++)
65+
{
66+
var @event = new ManualResetEvent(false);
67+
events[i] = @event;
68+
ThreadPool.QueueUserWorkItem(s =>
69+
{
70+
try
71+
{
72+
Run(ids);
73+
}
74+
catch (Exception ex)
75+
{
76+
exceptions.Add(ex);
77+
}
78+
finally
79+
{
80+
@event.Set();
81+
}
82+
});
83+
}
84+
WaitHandle.WaitAll(events);
85+
Assert.IsEmpty(exceptions);
86+
}
87+
88+
[Test]
89+
public void TestQueryWithContains()
90+
{
91+
var ids = new List<Guid>
92+
{
93+
Guid.NewGuid(),
94+
Guid.NewGuid(),
95+
};
96+
Run(ids);
97+
}
98+
99+
private void Run(ICollection<Guid> ids)
100+
{
101+
using (var session = sessions.OpenSession())
102+
using (session.BeginTransaction())
103+
{
104+
var result = session.Query<TestEntity>()
105+
.Where(entity => ids.Contains(entity.Id))
106+
.ToList();
107+
108+
Assert.That(result.Count, Is.EqualTo(0));
109+
}
110+
}
111+
112+
public class TestEntity
113+
{
114+
public virtual Guid Id { get; set; }
115+
}
116+
}
117+
}

src/NHibernate.Test/NHibernate.Test.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,8 @@
678678
<Compile Include="NHSpecificTest\NH3058\SampleTest.cs" />
679679
<Compile Include="NHSpecificTest\NH1818\DomainClass.cs" />
680680
<Compile Include="NHSpecificTest\NH1818\Fixture1818.cs" />
681+
<Compile Include="NHSpecificTest\NH3428\Entity.cs" />
682+
<Compile Include="NHSpecificTest\NH3428\Fixture.cs" />
681683
<Compile Include="NHSpecificTest\NH3408\Fixture.cs" />
682684
<Compile Include="NHSpecificTest\NH3408\Model.cs" />
683685
<Compile Include="NHSpecificTest\NH2297\CustomCompositeUserType.cs" />
@@ -1079,6 +1081,7 @@
10791081
<Compile Include="NHSpecificTest\NH3153\Fixture.cs" />
10801082
<Compile Include="MappingByCode\IntegrationTests\NH3105\Model.cs" />
10811083
<Compile Include="MappingByCode\IntegrationTests\NH3105\Fixture.cs" />
1084+
<Compile Include="NHSpecificTest\NH3436\Fixture.cs" />
10821085
<Compile Include="NHSpecificTest\NH941\Domain.cs" />
10831086
<Compile Include="NHSpecificTest\NH941\Fixture.cs" />
10841087
<Compile Include="NHSpecificTest\NH941\FixtureUsingList.cs" />
@@ -2957,6 +2960,7 @@
29572960
<EmbeddedResource Include="NHSpecificTest\NH3058\Mappings.hbm.xml" />
29582961
<EmbeddedResource Include="NHSpecificTest\NH2985\Mappings.hbm.xml" />
29592962
<EmbeddedResource Include="NHSpecificTest\NH1818\Mappings.hbm.xml" />
2963+
<EmbeddedResource Include="NHSpecificTest\NH3428\Mappings.hbm.xml" />
29602964
<EmbeddedResource Include="NHSpecificTest\NH3408\Mappings.hbm.xml" />
29612965
<EmbeddedResource Include="NHSpecificTest\NH2408\Mappings.hbm.xml" />
29622966
<EmbeddedResource Include="NHSpecificTest\NH2297\MappingsNames.hbm.xml" />

src/NHibernate/Engine/Query/HQLQueryPlan.cs

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

55
using NHibernate.Event;
66
using NHibernate.Hql;
7+
using NHibernate.Linq;
78
using NHibernate.Type;
89
using NHibernate.Util;
910

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

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

src/NHibernate/Engine/Query/QueryExpressionPlan.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using NHibernate.Hql;
4+
using NHibernate.Linq;
45

56
namespace NHibernate.Engine.Query
67
{
@@ -20,9 +21,20 @@ protected QueryExpressionPlan(string key, IQueryTranslator[] translators)
2021
{
2122
}
2223

24+
private QueryExpressionPlan(HQLQueryPlan source, IQueryExpression expression)
25+
: base(source)
26+
{
27+
QueryExpression = expression;
28+
}
29+
2330
protected static IQueryTranslator[] CreateTranslators(IQueryExpression queryExpression, string collectionRole, bool shallow, IDictionary<string, IFilter> enabledFilters, ISessionFactoryImplementor factory)
2431
{
2532
return factory.Settings.QueryTranslatorFactory.CreateQueryTranslators(queryExpression, collectionRole, shallow, enabledFilters, factory);
2633
}
34+
35+
public QueryExpressionPlan Copy(IQueryExpression expression)
36+
{
37+
return new QueryExpressionPlan(this, expression);
38+
}
2739
}
2840
}

src/NHibernate/Engine/Query/QueryPlanCache.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public IQueryPlan GetHQLQueryPlan(string queryString, bool shallow, IDictionary<
5656
public IQueryExpressionPlan GetHQLQueryPlan(IQueryExpression queryExpression, bool shallow, IDictionary<string, IFilter> enabledFilters)
5757
{
5858
var key = new HQLQueryPlanKey(queryExpression, shallow, enabledFilters);
59-
var plan = (IQueryExpressionPlan)planCache[key];
59+
var plan = (QueryExpressionPlan)planCache[key];
6060

6161
if (plan == null)
6262
{
@@ -83,8 +83,12 @@ public IQueryExpressionPlan GetHQLQueryPlan(IQueryExpression queryExpression, bo
8383
// for cases when we have list parameters in query, like @p1.Contains(...),
8484
// it does, and then it uses parameters from first try.
8585
//TODO: cache only required parts of QueryExpression
86-
planExpression._expression = expression._expression;
87-
planExpression._constantToParameterMap = expression._constantToParameterMap;
86+
87+
//NH-3436
88+
// We have to return new instance plan with it's own query expression
89+
// because other treads can override queryexpression of current plan during execution of query if we will use cached instance of plan
90+
expression.CopyExpressionTranslation(planExpression);
91+
plan = plan.Copy(expression);
8892
}
8993
}
9094

0 commit comments

Comments
 (0)