Skip to content

Commit a45ab82

Browse files
fixup!  Implement universal query batch
Get back to simpler Loader code
1 parent 82869f0 commit a45ab82

File tree

4 files changed

+105
-126
lines changed

4 files changed

+105
-126
lines changed

src/NHibernate/Async/Loader/Loader.cs

Lines changed: 30 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,11 +1165,26 @@ protected Task<IList> ListAsync(ISessionImplementor session, QueryParameters que
11651165
/// <param name="querySpaces"></param>
11661166
/// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param>
11671167
/// <returns></returns>
1168-
protected async Task<IList> ListAsync(ISessionImplementor session, QueryParameters queryParameters, ISet<string> querySpaces, CancellationToken cancellationToken)
1168+
protected Task<IList> ListAsync(ISessionImplementor session, QueryParameters queryParameters, ISet<string> querySpaces, CancellationToken cancellationToken)
11691169
{
1170-
cancellationToken.ThrowIfCancellationRequested();
1171-
return await (ListUsingQueryCacheOrNullAsync(session, queryParameters, querySpaces, cancellationToken)).ConfigureAwait(false)
1172-
?? await (ListIgnoreQueryCacheAsync(session, queryParameters, cancellationToken)).ConfigureAwait(false);
1170+
if (cancellationToken.IsCancellationRequested)
1171+
{
1172+
return Task.FromCanceled<IList>(cancellationToken);
1173+
}
1174+
try
1175+
{
1176+
var cacheable = IsCacheable(queryParameters);
1177+
1178+
if (cacheable)
1179+
{
1180+
return ListUsingQueryCacheAsync(session, queryParameters, querySpaces, cancellationToken);
1181+
}
1182+
return ListIgnoreQueryCacheAsync(session, queryParameters, cancellationToken);
1183+
}
1184+
catch (Exception ex)
1185+
{
1186+
return Task.FromException<IList>(ex);
1187+
}
11731188
}
11741189

11751190
private async Task<IList> ListIgnoreQueryCacheAsync(ISessionImplementor session, QueryParameters queryParameters, CancellationToken cancellationToken)
@@ -1178,53 +1193,27 @@ private async Task<IList> ListIgnoreQueryCacheAsync(ISessionImplementor session,
11781193
return GetResultList(await (DoListAsync(session, queryParameters, cancellationToken)).ConfigureAwait(false), queryParameters.ResultTransformer);
11791194
}
11801195

1181-
internal async Task ProcessCachedResultsAsync(
1182-
ISessionImplementor session,
1183-
QueryParameters queryParameters,
1184-
ISet<string> querySpaces,
1185-
Action<IQueryCache, QueryKey, IList> cacheProcessingLogic, CancellationToken cancellationToken)
1196+
private async Task<IList> ListUsingQueryCacheAsync(ISessionImplementor session, QueryParameters queryParameters, ISet<string> querySpaces, CancellationToken cancellationToken)
11861197
{
11871198
cancellationToken.ThrowIfCancellationRequested();
1188-
bool cacheable = _factory.Settings.IsQueryCacheEnabled && queryParameters.Cacheable;
1199+
IQueryCache queryCache = _factory.GetQueryCache(queryParameters.CacheRegion);
11891200

1190-
if (!cacheable)
1191-
return;
1192-
1193-
var queryCache = _factory.GetQueryCache(queryParameters.CacheRegion);
1194-
var key = GenerateQueryKey(session, queryParameters);
1201+
QueryKey key = GenerateQueryKey(session, queryParameters);
11951202

11961203
IList result = await (GetResultFromQueryCacheAsync(session, queryParameters, querySpaces, queryCache, key, cancellationToken)).ConfigureAwait(false);
1197-
cacheProcessingLogic(queryCache, key, result);
1198-
}
11991204

1200-
private async Task<IList> ListUsingQueryCacheOrNullAsync(ISessionImplementor session, QueryParameters queryParameters, ISet<string> querySpaces, CancellationToken cancellationToken)
1201-
{
1202-
cancellationToken.ThrowIfCancellationRequested();
1203-
IList cachedResults = null;
1204-
await (ProcessCachedResultsAsync(
1205-
session,
1206-
queryParameters,
1207-
querySpaces,
1208-
(queryCache, cacheKey, results) =>
1209-
{
1210-
if (results == null)
1211-
{
1212-
results = DoList(session, queryParameters, cacheKey.ResultTransformer);
1213-
PutResultInQueryCache(session, queryParameters, queryCache, cacheKey, results);
1214-
}
1215-
1216-
TransformCachedResults(queryParameters, cacheKey.ResultTransformer, ref results);
1217-
cachedResults = results;
1218-
}, cancellationToken)).ConfigureAwait(false);
1205+
if (result == null)
1206+
{
1207+
result = await (DoListAsync(session, queryParameters, key.ResultTransformer, cancellationToken)).ConfigureAwait(false);
1208+
await (PutResultInQueryCacheAsync(session, queryParameters, queryCache, key, result, cancellationToken)).ConfigureAwait(false);
1209+
}
12191210

1220-
//means cache is disabled
1221-
if (cachedResults == null)
1222-
return null;
1211+
result = TransformCacheableResults(queryParameters, key.ResultTransformer, result);
12231212

1224-
return GetResultList(cachedResults, queryParameters.ResultTransformer);
1213+
return GetResultList(result, queryParameters.ResultTransformer);
12251214
}
12261215

1227-
private async Task<IList> GetResultFromQueryCacheAsync(ISessionImplementor session, QueryParameters queryParameters,
1216+
internal async Task<IList> GetResultFromQueryCacheAsync(ISessionImplementor session, QueryParameters queryParameters,
12281217
ISet<string> querySpaces, IQueryCache queryCache,
12291218
QueryKey key, CancellationToken cancellationToken)
12301219
{

src/NHibernate/Async/Multi/QueryBatchItemBase.cs

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ namespace NHibernate.Multi
2525
public abstract partial class QueryBatchItemBase<TResult> : IQueryBatchItem<TResult>
2626
{
2727

28+
/// <summary>
29+
/// Gets the commands to execute for getting the not-already cached results of this query. Does retrieves
30+
/// already cached results by side-effect.
31+
/// </summary>
32+
/// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param>
33+
/// <returns>The commands for obtaining the results not already cached.</returns>
2834
public async Task<IEnumerable<ISqlCommand>> GetCommandsAsync(CancellationToken cancellationToken)
2935
{
3036
cancellationToken.ThrowIfCancellationRequested();
@@ -33,23 +39,20 @@ public async Task<IEnumerable<ISqlCommand>> GetCommandsAsync(CancellationToken c
3339
{
3440
var qi = _queryInfos[index];
3541

36-
IList resultsFromCache = null;
37-
await (qi.Loader.ProcessCachedResultsAsync(
38-
Session,
39-
qi.Parameters,
40-
qi.QuerySpaces,
41-
(cache, key, results) =>
42-
{
43-
qi.CacheKey = key;
44-
qi.Cache = cache;
45-
resultsFromCache = results;
46-
}, cancellationToken)).ConfigureAwait(false);
47-
48-
if (resultsFromCache != null)
42+
if (qi.Loader.IsCacheable(qi.Parameters))
4943
{
50-
qi.Cache = null;
51-
_loaderResults[index] = resultsFromCache;
52-
continue;
44+
// Check if the results are available in the cache
45+
qi.Cache = Session.Factory.GetQueryCache(qi.Parameters.CacheRegion);
46+
qi.CacheKey = qi.Loader.GenerateQueryKey(Session, qi.Parameters);
47+
var resultsFromCache = await (qi.Loader.GetResultFromQueryCacheAsync(Session, qi.Parameters, qi.QuerySpaces, qi.Cache, qi.CacheKey, cancellationToken)).ConfigureAwait(false);
48+
49+
if (resultsFromCache != null)
50+
{
51+
// Cached results available, skip the command for them and stores them.
52+
qi.Cache = null;
53+
_loaderResults[index] = resultsFromCache;
54+
continue;
55+
}
5356
}
5457
yields.Add(qi.Loader.CreateSqlCommand(qi.Parameters, Session));
5558
}

src/NHibernate/Loader/Loader.cs

Lines changed: 37 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1637,76 +1637,61 @@ protected IList List(ISessionImplementor session, QueryParameters queryParameter
16371637
/// <returns></returns>
16381638
protected IList List(ISessionImplementor session, QueryParameters queryParameters, ISet<string> querySpaces)
16391639
{
1640-
return ListUsingQueryCacheOrNull(session, queryParameters, querySpaces)
1641-
?? ListIgnoreQueryCache(session, queryParameters);
1640+
var cacheable = IsCacheable(queryParameters);
1641+
1642+
if (cacheable)
1643+
{
1644+
return ListUsingQueryCache(session, queryParameters, querySpaces);
1645+
}
1646+
return ListIgnoreQueryCache(session, queryParameters);
1647+
}
1648+
1649+
internal bool IsCacheable(QueryParameters queryParameters)
1650+
{
1651+
return _factory.Settings.IsQueryCacheEnabled && queryParameters.Cacheable;
16421652
}
16431653

16441654
private IList ListIgnoreQueryCache(ISessionImplementor session, QueryParameters queryParameters)
16451655
{
16461656
return GetResultList(DoList(session, queryParameters), queryParameters.ResultTransformer);
16471657
}
16481658

1649-
internal void ProcessCachedResults(
1650-
ISessionImplementor session,
1651-
QueryParameters queryParameters,
1652-
ISet<string> querySpaces,
1653-
Action<IQueryCache, QueryKey, IList> cacheProcessingLogic)
1659+
private IList ListUsingQueryCache(ISessionImplementor session, QueryParameters queryParameters, ISet<string> querySpaces)
16541660
{
1655-
bool cacheable = _factory.Settings.IsQueryCacheEnabled && queryParameters.Cacheable;
1661+
IQueryCache queryCache = _factory.GetQueryCache(queryParameters.CacheRegion);
16561662

1657-
if (!cacheable)
1658-
return;
1659-
1660-
var queryCache = _factory.GetQueryCache(queryParameters.CacheRegion);
1661-
var key = GenerateQueryKey(session, queryParameters);
1663+
QueryKey key = GenerateQueryKey(session, queryParameters);
16621664

16631665
IList result = GetResultFromQueryCache(session, queryParameters, querySpaces, queryCache, key);
1664-
cacheProcessingLogic(queryCache, key, result);
1665-
}
1666-
1667-
private IList ListUsingQueryCacheOrNull(ISessionImplementor session, QueryParameters queryParameters, ISet<string> querySpaces)
1668-
{
1669-
IList cachedResults = null;
1670-
ProcessCachedResults(
1671-
session,
1672-
queryParameters,
1673-
querySpaces,
1674-
(queryCache, cacheKey, results) =>
1675-
{
1676-
if (results == null)
1677-
{
1678-
results = DoList(session, queryParameters, cacheKey.ResultTransformer);
1679-
PutResultInQueryCache(session, queryParameters, queryCache, cacheKey, results);
1680-
}
16811666

1682-
TransformCachedResults(queryParameters, cacheKey.ResultTransformer, ref results);
1683-
cachedResults = results;
1684-
});
1667+
if (result == null)
1668+
{
1669+
result = DoList(session, queryParameters, key.ResultTransformer);
1670+
PutResultInQueryCache(session, queryParameters, queryCache, key, result);
1671+
}
16851672

1686-
//means cache is disabled
1687-
if (cachedResults == null)
1688-
return null;
1673+
result = TransformCacheableResults(queryParameters, key.ResultTransformer, result);
16891674

1690-
return GetResultList(cachedResults, queryParameters.ResultTransformer);
1675+
return GetResultList(result, queryParameters.ResultTransformer);
16911676
}
16921677

1693-
internal void TransformCachedResults(QueryParameters queryParameters, CacheableResultTransformer transformer, ref IList result)
1678+
internal IList TransformCacheableResults(QueryParameters queryParameters, CacheableResultTransformer transformer, IList result)
16941679
{
1695-
IResultTransformer resolvedTransformer = ResolveResultTransformer(queryParameters.ResultTransformer);
1696-
if (resolvedTransformer != null)
1697-
{
1698-
result = (AreResultSetRowsTransformedImmediately()
1699-
? transformer.RetransformResults(
1700-
result,
1701-
ResultRowAliases,
1702-
queryParameters.ResultTransformer,
1703-
IncludeInResultRow)
1704-
: transformer.UntransformToTuples(result)
1705-
);
1706-
}
1680+
var resolvedTransformer = ResolveResultTransformer(queryParameters.ResultTransformer);
1681+
if (resolvedTransformer == null)
1682+
return result;
1683+
1684+
return (AreResultSetRowsTransformedImmediately()
1685+
? transformer.RetransformResults(
1686+
result,
1687+
ResultRowAliases,
1688+
queryParameters.ResultTransformer,
1689+
IncludeInResultRow)
1690+
: transformer.UntransformToTuples(result)
1691+
);
17071692
}
17081693

1709-
private QueryKey GenerateQueryKey(ISessionImplementor session, QueryParameters queryParameters)
1694+
internal QueryKey GenerateQueryKey(ISessionImplementor session, QueryParameters queryParameters)
17101695
{
17111696
ISet<FilterKey> filterKeys = FilterKey.CreateFilterKeys(session.EnabledFilters);
17121697
return new QueryKey(Factory, SqlString, queryParameters, filterKeys,
@@ -1720,7 +1705,7 @@ private CacheableResultTransformer CreateCacheableResultTransformer(QueryParamet
17201705
queryParameters.HasAutoDiscoverScalarTypes, SqlString);
17211706
}
17221707

1723-
private IList GetResultFromQueryCache(ISessionImplementor session, QueryParameters queryParameters,
1708+
internal IList GetResultFromQueryCache(ISessionImplementor session, QueryParameters queryParameters,
17241709
ISet<string> querySpaces, IQueryCache queryCache,
17251710
QueryKey key)
17261711
{

src/NHibernate/Multi/QueryBatchItemBase.cs

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -48,29 +48,31 @@ public virtual void Init(ISessionImplementor session)
4848
_finalResults = null;
4949
}
5050

51+
/// <summary>
52+
/// Gets the commands to execute for getting the not-already cached results of this query. Does retrieves
53+
/// already cached results by side-effect.
54+
/// </summary>
55+
/// <returns>The commands for obtaining the results not already cached.</returns>
5156
public IEnumerable<ISqlCommand> GetCommands()
5257
{
5358
for (var index = 0; index < _queryInfos.Count; index++)
5459
{
5560
var qi = _queryInfos[index];
5661

57-
IList resultsFromCache = null;
58-
qi.Loader.ProcessCachedResults(
59-
Session,
60-
qi.Parameters,
61-
qi.QuerySpaces,
62-
(cache, key, results) =>
63-
{
64-
qi.CacheKey = key;
65-
qi.Cache = cache;
66-
resultsFromCache = results;
67-
});
68-
69-
if (resultsFromCache != null)
62+
if (qi.Loader.IsCacheable(qi.Parameters))
7063
{
71-
qi.Cache = null;
72-
_loaderResults[index] = resultsFromCache;
73-
continue;
64+
// Check if the results are available in the cache
65+
qi.Cache = Session.Factory.GetQueryCache(qi.Parameters.CacheRegion);
66+
qi.CacheKey = qi.Loader.GenerateQueryKey(Session, qi.Parameters);
67+
var resultsFromCache = qi.Loader.GetResultFromQueryCache(Session, qi.Parameters, qi.QuerySpaces, qi.Cache, qi.CacheKey);
68+
69+
if (resultsFromCache != null)
70+
{
71+
// Cached results available, skip the command for them and stores them.
72+
qi.Cache = null;
73+
_loaderResults[index] = resultsFromCache;
74+
continue;
75+
}
7476
}
7577

7678
yield return qi.Loader.CreateSqlCommand(qi.Parameters, Session);
@@ -90,7 +92,7 @@ public IEnumerable<Func<DbDataReader, int>> GetResultSetHandler()
9092
//Skip processing for items already loaded from cache
9193
if (_queryInfos[i].CacheKey?.ResultTransformer != null && _loaderResults[i] != null)
9294
{
93-
loader.TransformCachedResults(queryParameters, _queryInfos[i].CacheKey.ResultTransformer, ref _loaderResults[i]);
95+
_loaderResults[i] = loader.TransformCacheableResults(queryParameters, _queryInfos[i].CacheKey.ResultTransformer, _loaderResults[i]);
9496
continue;
9597
}
9698

0 commit comments

Comments
 (0)