Skip to content

Commit a6f5fe7

Browse files
committed
fixup! Implement universal query batch
Expose afterLoad callback Add ovverides with aggregator selector
1 parent b147a8d commit a6f5fe7

File tree

4 files changed

+79
-36
lines changed

4 files changed

+79
-36
lines changed

src/NHibernate.Test/Async/Futures/QueryBatchFixture.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -153,33 +153,34 @@ public async Task CanFetchCollectionInBatchAsync()
153153
}
154154

155155
[Test]
156-
public async Task OnAfterLoadAsync()
156+
public async Task AfterLoadCallbackAsync()
157157
{
158158
using (var session = OpenSession())
159159
{
160160
var batch = session.CreateQueryBatch();
161161
IList<EntityComplex> results = null;
162-
var batchItem = LinqBatchItem.Create(session.Query<EntityComplex>().WithOptions(o => o.SetCacheable(true)));
163-
batchItem.OnAfterLoad += list => results = list;
164-
batch.Add(batchItem);
165-
162+
int count = 0;
163+
batch.Add(session.Query<EntityComplex>().WithOptions(o => o.SetCacheable(true)), r => results = r);
164+
batch.Add(session.Query<EntityComplex>().WithOptions(o => o.SetCacheable(true)), ec => ec.Count(), r => count = r);
166165
await (batch.ExecuteAsync(CancellationToken.None));
167166

168167
Assert.That(results, Is.Not.Null);
168+
Assert.That(count, Is.GreaterThan(0));
169169
}
170170

171171
using (var sqlLog = new SqlLogSpy())
172172
using (var session = OpenSession())
173173
{
174174
var batch = session.CreateQueryBatch();
175175
IList<EntityComplex> results = null;
176-
var batchItem = LinqBatchItem.Create(session.Query<EntityComplex>().WithOptions(o => o.SetCacheable(true)));
177-
batchItem.OnAfterLoad += list => results = list;
178-
batch.Add(batchItem);
176+
int count = 0;
177+
batch.Add(session.Query<EntityComplex>().WithOptions(o => o.SetCacheable(true)), r => results = r);
178+
batch.Add(session.Query<EntityComplex>().WithOptions(o => o.SetCacheable(true)), ec => ec.Count(), r => count = r);
179179

180180
await (batch.ExecuteAsync(CancellationToken.None));
181181

182182
Assert.That(results, Is.Not.Null);
183+
Assert.That(count, Is.GreaterThan(0));
183184
Assert.That(sqlLog.Appender.GetEvents().Length, Is.EqualTo(0), "Query is expected to be retrieved from cache");
184185
}
185186
}

src/NHibernate.Test/Futures/QueryBatchFixture.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -141,33 +141,34 @@ public void CanFetchCollectionInBatch()
141141
}
142142

143143
[Test]
144-
public void OnAfterLoad()
144+
public void AfterLoadCallback()
145145
{
146146
using (var session = OpenSession())
147147
{
148148
var batch = session.CreateQueryBatch();
149149
IList<EntityComplex> results = null;
150-
var batchItem = LinqBatchItem.Create(session.Query<EntityComplex>().WithOptions(o => o.SetCacheable(true)));
151-
batchItem.OnAfterLoad += list => results = list;
152-
batch.Add(batchItem);
153-
150+
int count = 0;
151+
batch.Add(session.Query<EntityComplex>().WithOptions(o => o.SetCacheable(true)), r => results = r);
152+
batch.Add(session.Query<EntityComplex>().WithOptions(o => o.SetCacheable(true)), ec => ec.Count(), r => count = r);
154153
batch.Execute();
155154

156155
Assert.That(results, Is.Not.Null);
156+
Assert.That(count, Is.GreaterThan(0));
157157
}
158158

159159
using (var sqlLog = new SqlLogSpy())
160160
using (var session = OpenSession())
161161
{
162162
var batch = session.CreateQueryBatch();
163163
IList<EntityComplex> results = null;
164-
var batchItem = LinqBatchItem.Create(session.Query<EntityComplex>().WithOptions(o => o.SetCacheable(true)));
165-
batchItem.OnAfterLoad += list => results = list;
166-
batch.Add(batchItem);
164+
int count = 0;
165+
batch.Add(session.Query<EntityComplex>().WithOptions(o => o.SetCacheable(true)), r => results = r);
166+
batch.Add(session.Query<EntityComplex>().WithOptions(o => o.SetCacheable(true)), ec => ec.Count(), r => count = r);
167167

168168
batch.Execute();
169169

170170
Assert.That(results, Is.Not.Null);
171+
Assert.That(count, Is.GreaterThan(0));
171172
Assert.That(sqlLog.Appender.GetEvents().Length, Is.EqualTo(0), "Query is expected to be retrieved from cache");
172173
}
173174
}

src/NHibernate/Multi/IQueryBatchItem.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ public interface IQueryBatchItem<TResult> : IQueryBatchItem
1616
/// Must be called only after <see cref="IQueryBatch.Execute"/>.
1717
/// </summary>
1818
IList<TResult> GetResults();
19-
19+
2020
/// <summary>
21-
/// Event is executed after results are loaded by batch.
21+
/// Callback is executed after results are loaded by batch.
2222
/// Loaded results are provided in action parameter.
2323
/// </summary>
2424
event Action<IList<TResult>> OnAfterLoad;

src/NHibernate/Multi/QueryBatchExtensions.cs

Lines changed: 59 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ public static partial class QueryBatchExtensions
1717
/// </summary>
1818
/// <param name="batch">The batch.</param>
1919
/// <param name="query">The query.</param>
20+
/// <param name="afterLoad">Callback to execute when query is loaded. Loaded results are provided as action parameter.</param>
2021
/// <exception cref="InvalidOperationException">Thrown if the batch has already been executed.</exception>
2122
/// <exception cref="ArgumentNullException">Thrown if <paramref name="query"/> is <see langword="null"/>.</exception>
2223
/// <returns>The batch instance for method chain.</returns>
23-
public static IQueryBatch Add<TResult>(this IQueryBatch batch, IQueryOver query)
24+
public static IQueryBatch Add<TResult>(this IQueryBatch batch, IQueryOver query, Action<IList<TResult>> afterLoad = null)
2425
{
25-
batch.Add(For<TResult>(query));
26-
return batch;
26+
return batch.Add(For<TResult>(query), afterLoad);
2727
}
2828

2929
/// <summary>
@@ -48,13 +48,13 @@ public static IQueryBatch Add<TResult>(this IQueryBatch batch, string key, IQuer
4848
/// </summary>
4949
/// <param name="batch">The batch.</param>
5050
/// <param name="query">The query.</param>
51+
/// <param name="afterLoad">Callback to execute when query is loaded. Loaded results are provided as action parameter.</param>
5152
/// <exception cref="InvalidOperationException">Thrown if the batch has already been executed.</exception>
5253
/// <exception cref="ArgumentNullException">Thrown if <paramref name="query"/> is <see langword="null"/>.</exception>
5354
/// <returns>The batch instance for method chain.</returns>
54-
public static IQueryBatch Add<TResult>(this IQueryBatch batch, IQueryOver<TResult> query)
55+
public static IQueryBatch Add<TResult>(this IQueryBatch batch, IQueryOver<TResult> query, Action<IList<TResult>> afterLoad = null)
5556
{
56-
batch.Add(For<TResult>(query));
57-
return batch;
57+
return batch.Add(For<TResult>(query), afterLoad);
5858
}
5959

6060
/// <summary>
@@ -77,13 +77,13 @@ public static IQueryBatch Add<TResult>(this IQueryBatch batch, string key, IQuer
7777
/// </summary>
7878
/// <param name="batch">The batch.</param>
7979
/// <param name="query">The query.</param>
80+
/// <param name="afterLoad">Callback to execute when query is loaded. Loaded results are provided as action parameter.</param>
8081
/// <exception cref="InvalidOperationException">Thrown if the batch has already been executed.</exception>
8182
/// <exception cref="ArgumentNullException">Thrown if <paramref name="query"/> is <see langword="null"/>.</exception>
8283
/// <returns>The batch instance for method chain.</returns>
83-
public static IQueryBatch Add<TResult>(this IQueryBatch batch, ICriteria query)
84+
public static IQueryBatch Add<TResult>(this IQueryBatch batch, ICriteria query, Action<IList<TResult>> afterLoad = null)
8485
{
85-
batch.Add(For<TResult>(query));
86-
return batch;
86+
return batch.Add(For<TResult>(query), afterLoad);
8787
}
8888

8989
/// <summary>
@@ -106,13 +106,13 @@ public static IQueryBatch Add<TResult>(this IQueryBatch batch, string key, ICrit
106106
/// </summary>
107107
/// <param name="batch">The batch.</param>
108108
/// <param name="query">The query.</param>
109+
/// <param name="afterLoad">Callback to execute when query is loaded. Loaded results are provided as action parameter.</param>
109110
/// <exception cref="InvalidOperationException">Thrown if the batch has already been executed.</exception>
110111
/// <exception cref="ArgumentNullException">Thrown if <paramref name="query"/> is <see langword="null"/>.</exception>
111112
/// <returns>The batch instance for method chain.</returns>
112-
public static IQueryBatch Add<TResult>(this IQueryBatch batch, DetachedCriteria query)
113+
public static IQueryBatch Add<TResult>(this IQueryBatch batch, DetachedCriteria query, Action<IList<TResult>> afterLoad = null)
113114
{
114-
batch.Add(For<TResult>(query));
115-
return batch;
115+
return batch.Add(For<TResult>(query), afterLoad);
116116
}
117117

118118
/// <summary>
@@ -135,13 +135,13 @@ public static IQueryBatch Add<TResult>(this IQueryBatch batch, string key, Detac
135135
/// </summary>
136136
/// <param name="batch">The batch.</param>
137137
/// <param name="query">The query.</param>
138+
/// <param name="afterLoad">Callback to execute when query is loaded. Loaded results are provided as action parameter.</param>
138139
/// <exception cref="InvalidOperationException">Thrown if the batch has already been executed.</exception>
139140
/// <exception cref="ArgumentNullException">Thrown if <paramref name="query"/> is <see langword="null"/>.</exception>
140141
/// <returns>The batch instance for method chain.</returns>
141-
public static IQueryBatch Add<TResult>(this IQueryBatch batch, IQuery query)
142+
public static IQueryBatch Add<TResult>(this IQueryBatch batch, IQuery query, Action<IList<TResult>> afterLoad = null)
142143
{
143-
batch.Add(For<TResult>(query));
144-
return batch;
144+
return batch.Add(For<TResult>(query), afterLoad);
145145
}
146146

147147
/// <summary>
@@ -164,13 +164,13 @@ public static IQueryBatch Add<TResult>(this IQueryBatch batch, string key, IQuer
164164
/// </summary>
165165
/// <param name="batch">The batch.</param>
166166
/// <param name="query">The query.</param>
167+
/// <param name="afterLoad">Callback to execute when query is loaded. Loaded results are provided as action parameter.</param>
167168
/// <exception cref="InvalidOperationException">Thrown if the batch has already been executed.</exception>
168169
/// <exception cref="ArgumentNullException">Thrown if <paramref name="query"/> is <see langword="null"/>.</exception>
169170
/// <returns>The batch instance for method chain.</returns>
170-
public static IQueryBatch Add<TResult>(this IQueryBatch batch, IQueryable<TResult> query)
171+
public static IQueryBatch Add<TResult>(this IQueryBatch batch, IQueryable<TResult> query, Action<IList<TResult>> afterLoad = null)
171172
{
172-
batch.Add(For(query));
173-
return batch;
173+
return batch.Add(For<TResult>(query), afterLoad);
174174
}
175175

176176
/// <summary>
@@ -188,6 +188,37 @@ public static IQueryBatch Add<TResult>(this IQueryBatch batch, string key, IQuer
188188
return batch;
189189
}
190190

191+
/// <summary>
192+
/// Adds a query to the batch.
193+
/// </summary>
194+
/// <param name="batch">The batch.</param>
195+
/// <param name="query">The query.</param>
196+
/// <param name="selector">An aggregation function to apply to <paramref name="query"/>.</param>
197+
/// <param name="afterLoad">Callback to execute when query is loaded. Loaded results are provided as action parameter.</param>
198+
/// <exception cref="InvalidOperationException">Thrown if the batch has already been executed.</exception>
199+
/// <exception cref="ArgumentNullException">Thrown if <paramref name="query"/> is <see langword="null"/>.</exception>
200+
/// <returns>The batch instance for method chain.</returns>
201+
public static IQueryBatch Add<TSource, TResult>(this IQueryBatch batch, IQueryable<TSource> query, Expression<Func<IQueryable<TSource>, TResult>> selector, Action<TResult> afterLoad = null)
202+
{
203+
return batch.Add(For(query, selector), afterLoad == null ? (Action<IList<TResult>>) null : list => afterLoad(list.FirstOrDefault()));
204+
}
205+
206+
/// <summary>
207+
/// Adds a query to the batch.
208+
/// </summary>
209+
/// <param name="batch">The batch.</param>
210+
/// <param name="key">A key for retrieval of the query result.</param>
211+
/// <param name="query">The query.</param>
212+
/// <param name="selector">An aggregation function to apply to <paramref name="query"/>.</param>
213+
/// <exception cref="InvalidOperationException">Thrown if the batch has already been executed.</exception>
214+
/// <exception cref="ArgumentNullException">Thrown if <paramref name="query"/> is <see langword="null"/>.</exception>
215+
/// <returns>The batch instance for method chain.</returns>
216+
public static IQueryBatch Add<TSource, TResult>(this IQueryBatch batch, string key, IQueryable<TSource> query, Expression<Func<IQueryable<TSource>, TResult>> selector)
217+
{
218+
batch.Add(key, For(query, selector));
219+
return batch;
220+
}
221+
191222
/// <summary>
192223
/// Sets the timeout in seconds for the underlying ADO.NET query.
193224
/// </summary>
@@ -324,6 +355,16 @@ private static CriteriaBatchItem<TResult> For<TResult>(IQueryOver query)
324355
return For<TResult>(query.RootCriteria);
325356
}
326357

358+
private static IQueryBatch Add<TResult>(this IQueryBatch batch, IQueryBatchItem<TResult> query, Action<IList<TResult>> afterLoad)
359+
{
360+
if (afterLoad != null)
361+
{
362+
query.OnAfterLoad += afterLoad;
363+
}
364+
batch.Add(query);
365+
return batch;
366+
}
367+
327368
#region Helper classes
328369

329370
partial class FutureValue<TResult> : IFutureValue<TResult>

0 commit comments

Comments
 (0)