Skip to content

Commit a62df45

Browse files
committed
Cache tuple without transformation for queries with fetches
1 parent 498778b commit a62df45

File tree

7 files changed

+263
-30
lines changed

7 files changed

+263
-30
lines changed

src/NHibernate.Test/Async/Criteria/ReadonlyTests/QueryOverCacheableTests.cs

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using System.Linq;
1212
using NHibernate.Cfg;
1313
using NHibernate.DomainModel.Northwind.Entities;
14+
using NHibernate.SqlCommand;
1415
using NUnit.Framework;
1516

1617
namespace NHibernate.Test.Criteria.ReadonlyTests
@@ -35,8 +36,8 @@ public async Task QueryIsCacheableAsync()
3536
Sfi.Statistics.Clear();
3637
await (Sfi.EvictQueriesAsync());
3738

38-
var x = await (db.Customers.Cacheable().ListAsync());
39-
var x2 = await (db.Customers.Cacheable().ListAsync());
39+
var x = await (db.Customers.Cacheable().Take(1).ListAsync());
40+
var x2 = await (db.Customers.Cacheable().Take(1).ListAsync());
4041

4142
Assert.That(Sfi.Statistics.QueryExecutionCount, Is.EqualTo(1), "Unexpected execution count");
4243
Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(1), "Unexpected cache put count");
@@ -49,8 +50,8 @@ public async Task QueryIsCacheable2Async()
4950
Sfi.Statistics.Clear();
5051
await (Sfi.EvictQueriesAsync());
5152

52-
var x = await (db.Customers.Cacheable().ListAsync());
53-
var x2 = await (db.Customers.ListAsync());
53+
var x = await (db.Customers.Cacheable().Take(1).ListAsync());
54+
var x2 = await (db.Customers.Take(1).ListAsync());
5455

5556
Assert.That(Sfi.Statistics.QueryExecutionCount, Is.EqualTo(2), "Unexpected execution count");
5657
Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(1), "Unexpected cache put count");
@@ -65,9 +66,9 @@ public async Task QueryIsCacheableWithRegionAsync()
6566
await (Sfi.EvictQueriesAsync("test"));
6667
await (Sfi.EvictQueriesAsync("other"));
6768

68-
var x = await (db.Customers.Cacheable().CacheRegion("test").ListAsync());
69-
var x2 = await (db.Customers.Cacheable().CacheRegion("test").ListAsync());
70-
var x3 = await (db.Customers.Cacheable().CacheRegion("other").ListAsync());
69+
var x = await (db.Customers.Cacheable().Take(1).CacheRegion("test").ListAsync());
70+
var x2 = await (db.Customers.Cacheable().Take(1).CacheRegion("test").ListAsync());
71+
var x3 = await (db.Customers.Cacheable().Take(1).CacheRegion("other").ListAsync());
7172

7273
Assert.That(Sfi.Statistics.QueryExecutionCount, Is.EqualTo(2), "Unexpected execution count");
7374
Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(2), "Unexpected cache put count");
@@ -88,16 +89,19 @@ public async Task CanBeCombinedWithFetchAsync()
8889

8990
await (db.Orders
9091
.Cacheable()
92+
.Take(1)
9193
.ListAsync());
9294

9395
await (db.Customers
9496
.Fetch(SelectMode.Fetch, x => x.Orders)
9597
.Cacheable()
98+
.Take(1)
9699
.ListAsync());
97100

98101
await (db.Orders
99102
.Fetch(SelectMode.Fetch, x => x.OrderLines)
100103
.Cacheable()
104+
.Take(1)
101105
.ListAsync());
102106

103107
var customer = await (db.Customers
@@ -165,7 +169,57 @@ public async Task FetchIsCacheableAsync()
165169
Assert.That(Sfi.Statistics.QueryCacheMissCount, Is.EqualTo(0), "Unexpected cache miss count");
166170
Assert.That(Sfi.Statistics.QueryCacheHitCount, Is.EqualTo(1), "Unexpected cache hit count");
167171
}
168-
172+
173+
174+
[Test]
175+
public async Task FetchIsCacheableForJoinAliasAsync()
176+
{
177+
Sfi.Statistics.Clear();
178+
await (Sfi.EvictQueriesAsync());
179+
180+
Order order;
181+
Customer customer = null;
182+
OrderLine orderLines = null;
183+
Product product = null;
184+
OrderLine prOrderLines = null;
185+
186+
order = (await (db.Orders
187+
.JoinAlias(x => x.Customer, () => customer)
188+
.JoinAlias(x => x.OrderLines, () => orderLines, JoinType.LeftOuterJoin)
189+
.JoinAlias(() => orderLines.Product, () => product)
190+
.JoinAlias(() => product.OrderLines, () => prOrderLines, JoinType.LeftOuterJoin)
191+
.Where(x => x.OrderId == 10248)
192+
.Cacheable()
193+
.ListAsync()))
194+
.First();
195+
196+
AssertFetchedOrder(order);
197+
198+
Assert.That(Sfi.Statistics.QueryExecutionCount, Is.EqualTo(1), "Unexpected execution count");
199+
Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(1), "Unexpected cache put count");
200+
Assert.That(Sfi.Statistics.QueryCacheMissCount, Is.EqualTo(1), "Unexpected cache miss count");
201+
202+
Sfi.Statistics.Clear();
203+
Session.Clear();
204+
205+
order = (await (db.Orders
206+
.JoinAlias(x => x.Customer, () => customer)
207+
.JoinAlias(x => x.OrderLines, () => orderLines, JoinType.LeftOuterJoin)
208+
.JoinAlias(() => orderLines.Product, () => product)
209+
.JoinAlias(() => product.OrderLines, () => prOrderLines, JoinType.LeftOuterJoin)
210+
.Where(x => x.OrderId == 10248)
211+
.Cacheable()
212+
.ListAsync()))
213+
.First();
214+
215+
AssertFetchedOrder(order);
216+
217+
Assert.That(Sfi.Statistics.QueryExecutionCount, Is.EqualTo(0), "Unexpected execution count");
218+
Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(0), "Unexpected cache put count");
219+
Assert.That(Sfi.Statistics.QueryCacheMissCount, Is.EqualTo(0), "Unexpected cache miss count");
220+
Assert.That(Sfi.Statistics.QueryCacheHitCount, Is.EqualTo(1), "Unexpected cache hit count");
221+
}
222+
169223
[Test]
170224
public async Task FutureFetchIsCacheableAsync()
171225
{
@@ -230,10 +284,12 @@ public async Task FutureFetchIsCacheableAsync()
230284

231285
private static void AssertFetchedOrder(Order order)
232286
{
287+
Assert.That(order.Customer, Is.Not.Null, "Expected the fetched Customer to be initialized");
233288
Assert.That(NHibernateUtil.IsInitialized(order.Customer), Is.True, "Expected the fetched Customer to be initialized");
234289
Assert.That(NHibernateUtil.IsInitialized(order.OrderLines), Is.True, "Expected the fetched OrderLines to be initialized");
235290
Assert.That(order.OrderLines, Has.Count.EqualTo(3), "Expected the fetched OrderLines to have 3 items");
236291
var orderLine = order.OrderLines.First();
292+
Assert.That(orderLine.Product, Is.Not.Null, "Expected the fetched Product to be initialized");
237293
Assert.That(NHibernateUtil.IsInitialized(orderLine.Product), Is.True, "Expected the fetched Product to be initialized");
238294
Assert.That(NHibernateUtil.IsInitialized(orderLine.Product.OrderLines), Is.True, "Expected the fetched OrderLines to be initialized");
239295
}

src/NHibernate.Test/Async/Linq/QueryCacheableTests.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using NHibernate.Cfg;
1313
using NHibernate.DomainModel.Northwind.Entities;
1414
using NHibernate.Linq;
15+
using NHibernate.Transform;
1516
using NUnit.Framework;
1617

1718
namespace NHibernate.Test.Linq
@@ -408,12 +409,55 @@ public async Task FutureFetchIsCachableAsync()
408409
Assert.That(Sfi.Statistics.QueryCacheHitCount, Is.EqualTo(2), "Unexpected cache hit count");
409410
}
410411

412+
[Test]
413+
public async Task CacheHqlQueryWithFetchAndTransformerThatChangeTupleAsync()
414+
{
415+
Sfi.Statistics.Clear();
416+
await (Sfi.EvictQueriesAsync());
417+
Order order;
418+
419+
// the combination of query and transformer doesn't make sense.
420+
// It's simply used as example of returned data being transformed before caching leading to mismatch between
421+
// Loader.ResultTypes collection and provided tuple
422+
order = await (session.CreateQuery("select o.Customer.CompanyName, o from Order o join fetch o.Customer")
423+
.SetMaxResults(1)
424+
.SetCacheable(true)
425+
.SetResultTransformer(Transformers.RootEntity)
426+
.UniqueResultAsync<Order>());
427+
428+
Assert.That(Sfi.Statistics.QueryExecutionCount, Is.EqualTo(1), "Unexpected execution count");
429+
Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(1), "Unexpected cache put count");
430+
Assert.That(Sfi.Statistics.QueryCacheMissCount, Is.EqualTo(1), "Unexpected cache miss count");
431+
Assert.That(order, Is.Not.Null);
432+
Assert.That(order.Customer, Is.Not.Null);
433+
Assert.That(NHibernateUtil.IsInitialized(order.Customer), Is.True);
434+
435+
session.Clear();
436+
Sfi.Statistics.Clear();
437+
438+
order = await (session.CreateQuery("select o.Customer.CompanyName, o from Order o join fetch o.Customer")
439+
.SetMaxResults(1)
440+
.SetCacheable(true)
441+
.SetResultTransformer(Transformers.RootEntity)
442+
.UniqueResultAsync<Order>());
443+
444+
Assert.That(Sfi.Statistics.QueryExecutionCount, Is.EqualTo(0), "Unexpected execution count");
445+
Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(0), "Unexpected cache put count");
446+
Assert.That(Sfi.Statistics.QueryCacheMissCount, Is.EqualTo(0), "Unexpected cache miss count");
447+
Assert.That(Sfi.Statistics.QueryCacheHitCount, Is.EqualTo(1), "Unexpected cache hit count");
448+
Assert.That(order, Is.Not.Null);
449+
Assert.That(order.Customer, Is.Not.Null);
450+
Assert.That(NHibernateUtil.IsInitialized(order.Customer), Is.True);
451+
}
452+
411453
private static void AssertFetchedOrder(Order order)
412454
{
455+
Assert.That(order.Customer, Is.Not.Null, "Expected the fetched Customer to be initialized");
413456
Assert.That(NHibernateUtil.IsInitialized(order.Customer), Is.True, "Expected the fetched Customer to be initialized");
414457
Assert.That(NHibernateUtil.IsInitialized(order.OrderLines), Is.True, "Expected the fetched OrderLines to be initialized");
415458
Assert.That(order.OrderLines, Has.Count.EqualTo(3), "Expected the fetched OrderLines to have 3 items");
416459
var orderLine = order.OrderLines.First();
460+
Assert.That(orderLine.Product, Is.Not.Null, "Expected the fetched Product to be initialized");
417461
Assert.That(NHibernateUtil.IsInitialized(orderLine.Product), Is.True, "Expected the fetched Product to be initialized");
418462
Assert.That(NHibernateUtil.IsInitialized(orderLine.Product.OrderLines), Is.True, "Expected the fetched OrderLines to be initialized");
419463
}

src/NHibernate.Test/Criteria/ReadonlyTests/QueryOverCacheableTests.cs

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Linq;
22
using NHibernate.Cfg;
33
using NHibernate.DomainModel.Northwind.Entities;
4+
using NHibernate.SqlCommand;
45
using NUnit.Framework;
56

67
namespace NHibernate.Test.Criteria.ReadonlyTests
@@ -24,8 +25,8 @@ public void QueryIsCacheable()
2425
Sfi.Statistics.Clear();
2526
Sfi.EvictQueries();
2627

27-
var x = db.Customers.Cacheable().List();
28-
var x2 = db.Customers.Cacheable().List();
28+
var x = db.Customers.Cacheable().Take(1).List();
29+
var x2 = db.Customers.Cacheable().Take(1).List();
2930

3031
Assert.That(Sfi.Statistics.QueryExecutionCount, Is.EqualTo(1), "Unexpected execution count");
3132
Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(1), "Unexpected cache put count");
@@ -38,8 +39,8 @@ public void QueryIsCacheable2()
3839
Sfi.Statistics.Clear();
3940
Sfi.EvictQueries();
4041

41-
var x = db.Customers.Cacheable().List();
42-
var x2 = db.Customers.List();
42+
var x = db.Customers.Cacheable().Take(1).List();
43+
var x2 = db.Customers.Take(1).List();
4344

4445
Assert.That(Sfi.Statistics.QueryExecutionCount, Is.EqualTo(2), "Unexpected execution count");
4546
Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(1), "Unexpected cache put count");
@@ -54,9 +55,9 @@ public void QueryIsCacheableWithRegion()
5455
Sfi.EvictQueries("test");
5556
Sfi.EvictQueries("other");
5657

57-
var x = db.Customers.Cacheable().CacheRegion("test").List();
58-
var x2 = db.Customers.Cacheable().CacheRegion("test").List();
59-
var x3 = db.Customers.Cacheable().CacheRegion("other").List();
58+
var x = db.Customers.Cacheable().Take(1).CacheRegion("test").List();
59+
var x2 = db.Customers.Cacheable().Take(1).CacheRegion("test").List();
60+
var x3 = db.Customers.Cacheable().Take(1).CacheRegion("other").List();
6061

6162
Assert.That(Sfi.Statistics.QueryExecutionCount, Is.EqualTo(2), "Unexpected execution count");
6263
Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(2), "Unexpected cache put count");
@@ -77,16 +78,19 @@ public void CanBeCombinedWithFetch()
7778

7879
db.Orders
7980
.Cacheable()
81+
.Take(1)
8082
.List();
8183

8284
db.Customers
8385
.Fetch(SelectMode.Fetch, x => x.Orders)
8486
.Cacheable()
87+
.Take(1)
8588
.List();
8689

8790
db.Orders
8891
.Fetch(SelectMode.Fetch, x => x.OrderLines)
8992
.Cacheable()
93+
.Take(1)
9094
.List();
9195

9296
var customer = db.Customers
@@ -154,7 +158,57 @@ public void FetchIsCacheable()
154158
Assert.That(Sfi.Statistics.QueryCacheMissCount, Is.EqualTo(0), "Unexpected cache miss count");
155159
Assert.That(Sfi.Statistics.QueryCacheHitCount, Is.EqualTo(1), "Unexpected cache hit count");
156160
}
157-
161+
162+
163+
[Test]
164+
public void FetchIsCacheableForJoinAlias()
165+
{
166+
Sfi.Statistics.Clear();
167+
Sfi.EvictQueries();
168+
169+
Order order;
170+
Customer customer = null;
171+
OrderLine orderLines = null;
172+
Product product = null;
173+
OrderLine prOrderLines = null;
174+
175+
order = db.Orders
176+
.JoinAlias(x => x.Customer, () => customer)
177+
.JoinAlias(x => x.OrderLines, () => orderLines, JoinType.LeftOuterJoin)
178+
.JoinAlias(() => orderLines.Product, () => product)
179+
.JoinAlias(() => product.OrderLines, () => prOrderLines, JoinType.LeftOuterJoin)
180+
.Where(x => x.OrderId == 10248)
181+
.Cacheable()
182+
.List()
183+
.First();
184+
185+
AssertFetchedOrder(order);
186+
187+
Assert.That(Sfi.Statistics.QueryExecutionCount, Is.EqualTo(1), "Unexpected execution count");
188+
Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(1), "Unexpected cache put count");
189+
Assert.That(Sfi.Statistics.QueryCacheMissCount, Is.EqualTo(1), "Unexpected cache miss count");
190+
191+
Sfi.Statistics.Clear();
192+
Session.Clear();
193+
194+
order = db.Orders
195+
.JoinAlias(x => x.Customer, () => customer)
196+
.JoinAlias(x => x.OrderLines, () => orderLines, JoinType.LeftOuterJoin)
197+
.JoinAlias(() => orderLines.Product, () => product)
198+
.JoinAlias(() => product.OrderLines, () => prOrderLines, JoinType.LeftOuterJoin)
199+
.Where(x => x.OrderId == 10248)
200+
.Cacheable()
201+
.List()
202+
.First();
203+
204+
AssertFetchedOrder(order);
205+
206+
Assert.That(Sfi.Statistics.QueryExecutionCount, Is.EqualTo(0), "Unexpected execution count");
207+
Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(0), "Unexpected cache put count");
208+
Assert.That(Sfi.Statistics.QueryCacheMissCount, Is.EqualTo(0), "Unexpected cache miss count");
209+
Assert.That(Sfi.Statistics.QueryCacheHitCount, Is.EqualTo(1), "Unexpected cache hit count");
210+
}
211+
158212
[Test]
159213
public void FutureFetchIsCacheable()
160214
{
@@ -219,10 +273,12 @@ public void FutureFetchIsCacheable()
219273

220274
private static void AssertFetchedOrder(Order order)
221275
{
276+
Assert.That(order.Customer, Is.Not.Null, "Expected the fetched Customer to be initialized");
222277
Assert.That(NHibernateUtil.IsInitialized(order.Customer), Is.True, "Expected the fetched Customer to be initialized");
223278
Assert.That(NHibernateUtil.IsInitialized(order.OrderLines), Is.True, "Expected the fetched OrderLines to be initialized");
224279
Assert.That(order.OrderLines, Has.Count.EqualTo(3), "Expected the fetched OrderLines to have 3 items");
225280
var orderLine = order.OrderLines.First();
281+
Assert.That(orderLine.Product, Is.Not.Null, "Expected the fetched Product to be initialized");
226282
Assert.That(NHibernateUtil.IsInitialized(orderLine.Product), Is.True, "Expected the fetched Product to be initialized");
227283
Assert.That(NHibernateUtil.IsInitialized(orderLine.Product.OrderLines), Is.True, "Expected the fetched OrderLines to be initialized");
228284
}

src/NHibernate.Test/Linq/QueryCacheableTests.cs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using NHibernate.Cfg;
33
using NHibernate.DomainModel.Northwind.Entities;
44
using NHibernate.Linq;
5+
using NHibernate.Transform;
56
using NUnit.Framework;
67

78
namespace NHibernate.Test.Linq
@@ -397,12 +398,55 @@ public void FutureFetchIsCachable()
397398
Assert.That(Sfi.Statistics.QueryCacheHitCount, Is.EqualTo(2), "Unexpected cache hit count");
398399
}
399400

401+
[Test]
402+
public void CacheHqlQueryWithFetchAndTransformerThatChangeTuple()
403+
{
404+
Sfi.Statistics.Clear();
405+
Sfi.EvictQueries();
406+
Order order;
407+
408+
// the combination of query and transformer doesn't make sense.
409+
// It's simply used as example of returned data being transformed before caching leading to mismatch between
410+
// Loader.ResultTypes collection and provided tuple
411+
order = session.CreateQuery("select o.Customer.CompanyName, o from Order o join fetch o.Customer")
412+
.SetMaxResults(1)
413+
.SetCacheable(true)
414+
.SetResultTransformer(Transformers.RootEntity)
415+
.UniqueResult<Order>();
416+
417+
Assert.That(Sfi.Statistics.QueryExecutionCount, Is.EqualTo(1), "Unexpected execution count");
418+
Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(1), "Unexpected cache put count");
419+
Assert.That(Sfi.Statistics.QueryCacheMissCount, Is.EqualTo(1), "Unexpected cache miss count");
420+
Assert.That(order, Is.Not.Null);
421+
Assert.That(order.Customer, Is.Not.Null);
422+
Assert.That(NHibernateUtil.IsInitialized(order.Customer), Is.True);
423+
424+
session.Clear();
425+
Sfi.Statistics.Clear();
426+
427+
order = session.CreateQuery("select o.Customer.CompanyName, o from Order o join fetch o.Customer")
428+
.SetMaxResults(1)
429+
.SetCacheable(true)
430+
.SetResultTransformer(Transformers.RootEntity)
431+
.UniqueResult<Order>();
432+
433+
Assert.That(Sfi.Statistics.QueryExecutionCount, Is.EqualTo(0), "Unexpected execution count");
434+
Assert.That(Sfi.Statistics.QueryCachePutCount, Is.EqualTo(0), "Unexpected cache put count");
435+
Assert.That(Sfi.Statistics.QueryCacheMissCount, Is.EqualTo(0), "Unexpected cache miss count");
436+
Assert.That(Sfi.Statistics.QueryCacheHitCount, Is.EqualTo(1), "Unexpected cache hit count");
437+
Assert.That(order, Is.Not.Null);
438+
Assert.That(order.Customer, Is.Not.Null);
439+
Assert.That(NHibernateUtil.IsInitialized(order.Customer), Is.True);
440+
}
441+
400442
private static void AssertFetchedOrder(Order order)
401443
{
444+
Assert.That(order.Customer, Is.Not.Null, "Expected the fetched Customer to be initialized");
402445
Assert.That(NHibernateUtil.IsInitialized(order.Customer), Is.True, "Expected the fetched Customer to be initialized");
403446
Assert.That(NHibernateUtil.IsInitialized(order.OrderLines), Is.True, "Expected the fetched OrderLines to be initialized");
404447
Assert.That(order.OrderLines, Has.Count.EqualTo(3), "Expected the fetched OrderLines to have 3 items");
405448
var orderLine = order.OrderLines.First();
449+
Assert.That(orderLine.Product, Is.Not.Null, "Expected the fetched Product to be initialized");
406450
Assert.That(NHibernateUtil.IsInitialized(orderLine.Product), Is.True, "Expected the fetched Product to be initialized");
407451
Assert.That(NHibernateUtil.IsInitialized(orderLine.Product.OrderLines), Is.True, "Expected the fetched OrderLines to be initialized");
408452
}

0 commit comments

Comments
 (0)