Skip to content

Commit 9f12369

Browse files
committed
Add async counterparts for Single(Key)/SingleOrDefault(Key)
1 parent 19baf81 commit 9f12369

6 files changed

Lines changed: 281 additions & 36 deletions

File tree

ChangeLog/7.2.1-dev.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[main] Added Query.SingleAsync()/SingleOrDefaultAsync and QueryEndpoint.SingleAsync()/SingleOrDefaultAsync methods

Orm/Xtensive.Orm/Orm/Providers/ChainingSessionHandler.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2009-2020 Xtensive LLC.
1+
// Copyright (C) 2009-2026 Xtensive LLC.
22
// This code is distributed under MIT license terms.
33
// See the License.txt file in the project root for more information.
44
// Created by: Alexander Nikolaev
@@ -138,6 +138,9 @@ public override EntityState FetchEntityState(Key key)
138138
return ChainedHandler.FetchEntityState(key);
139139
}
140140

141+
/// <inheritdoc/>
142+
public override Task<EntityState> FetchEntityStateAsync(Key key, CancellationToken token = default) => ChainedHandler.FetchEntityStateAsync(key, token);
143+
141144
/// <inheritdoc/>
142145
public override void FetchField(Key key, FieldInfo field)
143146
{

Orm/Xtensive.Orm/Orm/Providers/SessionHandler.Fetching.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2009-2020 Xtensive LLC.
1+
// Copyright (C) 2009-2026 Xtensive LLC.
22
// This code is distributed under MIT license terms.
33
// See the License.txt file in the project root for more information.
44
// Created by: Denis Krjuchkov
@@ -36,7 +36,7 @@ partial class SessionHandler
3636
/// <param name="key">The key.</param>
3737
/// <param name="type">The type of the <see cref="Entity"/>.</param>
3838
/// <param name="descriptors">The descriptors of fields which values will be loaded.</param>
39-
/// <param name="token">The token to cancel this operation</param>
39+
/// <param name="token">The token to cancel this operation.</param>
4040
/// <returns>A <see cref="StrongReferenceContainer"/> which can be used to save
4141
/// a strong reference to a fetched <see cref="Entity"/>.</returns>
4242
public abstract Task<StrongReferenceContainer> PrefetchAsync(
@@ -57,7 +57,7 @@ public abstract Task<StrongReferenceContainer> PrefetchAsync(
5757
/// <see langword="await"/> to ensure that all asynchronous operations have completed before calling
5858
/// another method in this session.</remarks>
5959
/// <param name="skipPersist">if set to <see langword="true"/> persist is not performed.</param>
60-
/// <param name="token">The token to cancel this operation</param>
60+
/// <param name="token">The token to cancel this operation.</param>
6161
/// <returns>A <see cref="StrongReferenceContainer"/> which can be used to save
6262
/// a strong reference to a fetched <see cref="Entity"/>.</returns>
6363
public abstract Task<StrongReferenceContainer> ExecutePrefetchTasksAsync(
@@ -79,6 +79,7 @@ public StrongReferenceContainer ExecutePrefetchTasks()
7979
/// <remarks>Multiple active operations in the same session instance are not supported. Use
8080
/// <see langword="await"/> to ensure that all asynchronous operations have completed before calling
8181
/// another method in this session.</remarks>
82+
/// <param name="token">The token to cancel this operation.</param>
8283
/// <returns>A <see cref="StrongReferenceContainer"/> which can be used to save
8384
/// a strong reference to a fetched <see cref="Entity"/>.</returns>
8485
public Task<StrongReferenceContainer> ExecutePrefetchTasksAsync(CancellationToken token = default)
@@ -90,9 +91,21 @@ public Task<StrongReferenceContainer> ExecutePrefetchTasksAsync(CancellationToke
9091
/// Fetches an <see cref="EntityState"/>.
9192
/// </summary>
9293
/// <param name="key">The key.</param>
93-
/// <returns>The key of fetched <see cref="EntityState"/>.</returns>
94+
/// <returns>Fetched <see cref="EntityState"/> for given <paramref name="key"/>.</returns>
9495
public abstract EntityState FetchEntityState(Key key);
9596

97+
/// <summary>
98+
/// Fetches an <see cref="EntityState"/>.
99+
/// </summary>
100+
/// <param name="key">The key.</param>
101+
/// <param name="token">The token to cancel this operation.</param>
102+
/// <returns>Fetched <see cref="EntityState"/> for given <paramref name="key"/>.</returns>
103+
public virtual Task<EntityState> FetchEntityStateAsync(Key key, CancellationToken token = default)
104+
{
105+
var result = FetchEntityState(key);
106+
return Task.FromResult(result);
107+
}
108+
96109
/// <summary>
97110
/// Fetches the field of an <see cref="Entity"/>.
98111
/// </summary>

Orm/Xtensive.Orm/Orm/Providers/SqlSessionHandler.Fetching.cs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2009-2020 Xtensive LLC.
1+
// Copyright (C) 2009-2026 Xtensive LLC.
22
// This code is distributed under MIT license terms.
33
// See the License.txt file in the project root for more information.
44
// Created by: Denis Krjuchkov
@@ -44,17 +44,23 @@ public override Task<StrongReferenceContainer> ExecutePrefetchTasksAsync(bool sk
4444
return prefetchManager.ExecuteTasksAsync(skipPersist, token);
4545
}
4646

47-
/// <summary>
48-
/// Fetches an <see cref="EntityState"/>.
49-
/// </summary>
50-
/// <param name="key">The key.</param>
51-
/// <returns>The key of fetched <see cref="EntityState"/>.</returns>
47+
/// <inheritdoc/>
5248
public override EntityState FetchEntityState(Key key)
5349
{
5450
var type = key.TypeReference.Type;
55-
prefetchManager.Prefetch(key, type,
51+
_ = prefetchManager.Prefetch(key, type,
5652
PrefetchHelper.GetCachedDescriptorsForFieldsLoadedByDefault(Session.Domain, type));
57-
prefetchManager.ExecuteTasks(true);
53+
_ = prefetchManager.ExecuteTasks(true);
54+
return LookupState(key, out var result) ? result : null;
55+
}
56+
57+
/// <inheritdoc/>
58+
public override async Task<EntityState> FetchEntityStateAsync(Key key, CancellationToken token = default)
59+
{
60+
var type = key.TypeReference.Type;
61+
_ = await prefetchManager.PrefetchAsync(key, type,
62+
PrefetchHelper.GetCachedDescriptorsForFieldsLoadedByDefault(Session.Domain, type), token).ConfigureAwait(false);
63+
_ = await prefetchManager.ExecuteTasksAsync(true).ConfigureAwait(false);
5864
return LookupState(key, out var result) ? result : null;
5965
}
6066

Orm/Xtensive.Orm/Orm/Query.cs

Lines changed: 111 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2009-2020 Xtensive LLC.
1+
// Copyright (C) 2009-2026 Xtensive LLC.
22
// This code is distributed under MIT license terms.
33
// See the License.txt file in the project root for more information.
44
// Created by: Dmitri Maximov
@@ -204,6 +204,21 @@ public static Entity Single(Key key)
204204
return Session.Demand().Query.Single(key);
205205
}
206206

207+
/// <summary>
208+
/// Resolves (gets) the <see cref="Entity"/> by the specified <paramref name="key"/>
209+
/// in the current <see cref="Session"/>.
210+
/// </summary>
211+
/// <param name="key">The key to resolve.</param>
212+
/// <param name="token">The token to cancel this operation.</param>
213+
/// <returns>
214+
/// The <see cref="Entity"/> specified <paramref name="key"/> identifies.
215+
/// </returns>
216+
/// <exception cref="KeyNotFoundException">Entity with the specified key is not found.</exception>
217+
public static ValueTask<Entity> SingleAsync(Key key, CancellationToken token = default)
218+
{
219+
return Session.Demand().Query.SingleAsync(key, token);
220+
}
221+
207222
/// <summary>
208223
/// Resolves (gets) the <see cref="Entity"/> by the specified <paramref name="key"/>
209224
/// in the current <see cref="Session"/>.
@@ -213,7 +228,8 @@ public static Entity Single(Key key)
213228
/// The <see cref="Entity"/> specified <paramref name="key"/> identifies.
214229
/// <see langword="null"/>, if there is no such entity.
215230
/// </returns>
216-
[CanBeNull] public static Entity SingleOrDefault(Key key)
231+
[CanBeNull]
232+
public static Entity SingleOrDefault(Key key)
217233
{
218234
return Session.Demand().Query.SingleOrDefault(key);
219235
}
@@ -222,18 +238,51 @@ [CanBeNull] public static Entity SingleOrDefault(Key key)
222238
/// Resolves (gets) the <see cref="Entity"/> by the specified <paramref name="key"/>
223239
/// in the current <see cref="Session"/>.
224240
/// </summary>
225-
/// <typeparam name="T">Type of the entity.</typeparam>
226241
/// <param name="key">The key to resolve.</param>
242+
/// <param name="token">The token to cancel this operation.</param>
227243
/// <returns>
228244
/// The <see cref="Entity"/> specified <paramref name="key"/> identifies.
229245
/// <see langword="null"/>, if there is no such entity.
230246
/// </returns>
247+
[CanBeNull]
248+
public static ValueTask<Entity> SingleOrDefaultAsync(Key key, CancellationToken token = default)
249+
{
250+
return Session.Demand().Query.SingleOrDefaultAsync(key, token);
251+
}
252+
253+
/// <summary>
254+
/// Resolves (gets) the <see cref="Entity"/> by the specified <paramref name="key"/>
255+
/// in the current <see cref="Session"/>.
256+
/// </summary>
257+
/// <typeparam name="T">Type of the entity.</typeparam>
258+
/// <param name="key">The key to resolve.</param>
259+
/// <returns>
260+
/// The <see cref="Entity"/> specified <paramref name="key"/> identifies.
261+
/// </returns>
262+
/// <exception cref="KeyNotFoundException">Entity with the specified key is not found.</exception>
231263
public static T Single<T>(Key key)
232264
where T : class, IEntity
233265
{
234266
return Session.Demand().Query.Single<T>(key);
235267
}
236268

269+
/// <summary>
270+
/// Resolves (gets) the <see cref="Entity"/> by the specified <paramref name="key"/>
271+
/// in the current <see cref="Session"/>.
272+
/// </summary>
273+
/// <typeparam name="T">Type of the entity.</typeparam>
274+
/// <param name="key">The key to resolve.</param>
275+
/// <param name="token">The token to cancel this operation.</param>
276+
/// <returns>
277+
/// The <see cref="Entity"/> specified <paramref name="key"/> identifies.
278+
/// </returns>
279+
/// <exception cref="KeyNotFoundException">Entity with the specified key is not found.</exception>
280+
public static Task<T> SingleAsync<T>(Key key, CancellationToken token = default)
281+
where T : class, IEntity
282+
{
283+
return Session.Demand().Query.SingleAsync<T>(key, token);
284+
}
285+
237286
/// <summary>
238287
/// Resolves (gets) the <see cref="Entity"/> by the specified <paramref name="keyValues"/>
239288
/// in the current <see cref="Session"/>.
@@ -242,14 +291,31 @@ public static T Single<T>(Key key)
242291
/// <param name="keyValues">Key values.</param>
243292
/// <returns>
244293
/// The <see cref="Entity"/> specified <paramref name="keyValues"/> identify.
245-
/// <see langword="null"/>, if there is no such entity.
246294
/// </returns>
295+
/// <exception cref="KeyNotFoundException">Entity with the specified key is not found.</exception>
247296
public static T Single<T>(params object[] keyValues)
248297
where T : class, IEntity
249298
{
250299
return Session.Demand().Query.Single<T>(keyValues);
251300
}
252301

302+
/// <summary>
303+
/// Resolves (gets) the <see cref="Entity"/> by the specified <paramref name="keyValues"/>
304+
/// in the current <see cref="Session"/>.
305+
/// </summary>
306+
/// <typeparam name="T">Type of the entity.</typeparam>
307+
/// <param name="keyValues">Key values.</param>
308+
/// <param name="token">The token to cancel this operation.</param>
309+
/// <returns>
310+
/// The <see cref="Entity"/> specified <paramref name="keyValues"/> identify.
311+
/// </returns>
312+
/// <exception cref="KeyNotFoundException">Entity with the specified key is not found.</exception>
313+
public static Task<T> SingleAsync<T>(object[] keyValues, CancellationToken token)
314+
where T : class, IEntity
315+
{
316+
return Session.Demand().Query.SingleAsync<T>(keyValues, token);
317+
}
318+
253319
/// <summary>
254320
/// Resolves (gets) the <see cref="Entity"/> by the specified <paramref name="key"/>
255321
/// in the current <see cref="Session"/>.
@@ -258,13 +324,33 @@ public static T Single<T>(params object[] keyValues)
258324
/// <param name="key">The key to resolve.</param>
259325
/// <returns>
260326
/// The <see cref="Entity"/> specified <paramref name="key"/> identifies.
327+
/// <see langword="null"/>, if there is no such entity.
261328
/// </returns>
262-
[CanBeNull] public static T SingleOrDefault<T>(Key key)
329+
[CanBeNull]
330+
public static T SingleOrDefault<T>(Key key)
263331
where T : class, IEntity
264332
{
265333
return Session.Demand().Query.SingleOrDefault<T>(key);
266334
}
267335

336+
/// <summary>
337+
/// Resolves (gets) the <see cref="Entity"/> by the specified <paramref name="key"/>
338+
/// in the current <see cref="Session"/>.
339+
/// </summary>
340+
/// <typeparam name="T">Type of the entity.</typeparam>
341+
/// <param name="key">The key to resolve.</param>
342+
/// <param name="token">The token to cancel this operation.</param>
343+
/// <returns>
344+
/// The <see cref="Entity"/> specified <paramref name="key"/> identifies.
345+
/// <see langword="null"/>, if there is no such entity.
346+
/// </returns>
347+
[CanBeNull]
348+
public static Task<T> SingleOrDefaultAsync<T>(Key key, CancellationToken token)
349+
where T : class, IEntity
350+
{
351+
return Session.Demand().Query.SingleOrDefaultAsync<T>(key, token);
352+
}
353+
268354
/// <summary>
269355
/// Resolves (gets) the <see cref="Entity"/> by the specified <paramref name="keyValues"/>
270356
/// in the current <see cref="Session"/>.
@@ -273,13 +359,32 @@ [CanBeNull] public static T SingleOrDefault<T>(Key key)
273359
/// <param name="keyValues">Key values.</param>
274360
/// <returns>
275361
/// The <see cref="Entity"/> specified <paramref name="keyValues"/> identify.
362+
/// <see langword="null"/>, if there is no such entity.
276363
/// </returns>
277-
[CanBeNull] public static T SingleOrDefault<T>(params object[] keyValues)
364+
[CanBeNull]
365+
public static T SingleOrDefault<T>(params object[] keyValues)
278366
where T : class, IEntity
279367
{
280368
return Session.Demand().Query.SingleOrDefault<T>(keyValues);
281369
}
282370

371+
/// <summary>
372+
/// Resolves (gets) the <see cref="Entity"/> by the specified <paramref name="keyValues"/>
373+
/// in the current <see cref="Session"/>.
374+
/// </summary>
375+
/// <typeparam name="T">Type of the entity.</typeparam>
376+
/// <param name="keyValues">Key values.</param>
377+
/// <param name="token">The token to cancel this operation.</param>
378+
/// <returns>
379+
/// The <see cref="Entity"/> specified <paramref name="keyValues"/> identify.
380+
/// <see langword="null"/>, if there is no such entity.
381+
/// </returns>
382+
public static Task<T> SingleOrDefault<T>(object[] keyValues, CancellationToken token)
383+
where T : class, IEntity
384+
{
385+
return Session.Demand().Query.SingleOrDefaultAsync<T>(keyValues, token);
386+
}
387+
283388
#region Execute
284389

285390
/// <summary>

0 commit comments

Comments
 (0)