Browse Source

Fix inconsistencies between the Entity Framework 6 and Entity Framework Core stores

pull/2527/head
Kévin Chalet 3 weeks ago
parent
commit
e5266daf9e
  1. 6
      src/OpenIddict.Abstractions/Managers/IOpenIddictApplicationManager.cs
  2. 6
      src/OpenIddict.Abstractions/Managers/IOpenIddictAuthorizationManager.cs
  3. 8
      src/OpenIddict.Abstractions/Managers/IOpenIddictResourceManager.cs
  4. 6
      src/OpenIddict.Abstractions/Managers/IOpenIddictScopeManager.cs
  5. 8
      src/OpenIddict.Abstractions/Managers/IOpenIddictSessionManager.cs
  6. 6
      src/OpenIddict.Abstractions/Managers/IOpenIddictTokenManager.cs
  7. 1
      src/OpenIddict.Core/Managers/OpenIddictResourceManager.cs
  8. 49
      src/OpenIddict.EntityFramework/OpenIddictEntityFrameworkHelpers.cs
  9. 67
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkApplicationStore.cs
  10. 109
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkAuthorizationStore.cs
  11. 27
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkResourceStore.cs
  12. 41
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkScopeStore.cs
  13. 84
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkSessionStore.cs
  14. 146
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkTokenStore.cs
  15. 6
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreApplicationStore.cs
  16. 61
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreAuthorizationStore.cs
  17. 2
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreResourceStore.cs
  18. 2
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreScopeStore.cs
  19. 32
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreSessionStore.cs
  20. 91
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreTokenStore.cs
  21. 2
      src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbApplicationStore.cs
  22. 2
      src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbAuthorizationStore.cs
  23. 2
      src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbResourceStore.cs
  24. 2
      src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbScopeStore.cs
  25. 2
      src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbSessionStore.cs
  26. 2
      src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbTokenStore.cs
  27. 10
      src/OpenIddict.Quartz/OpenIddictQuartzJob.cs

6
src/OpenIddict.Abstractions/Managers/IOpenIddictApplicationManager.cs

@ -19,10 +19,8 @@ namespace OpenIddict.Abstractions;
/// </summary>
/// <remarks>
/// Note: this interface is not meant to be implemented by custom managers,
/// that should inherit from the generic OpenIddictApplicationManager class.
/// It is primarily intended to be used by services that cannot easily depend
/// on the generic application manager. The actual application entity type
/// is automatically determined at runtime based on the OpenIddict core options.
/// that should inherit from the generic class. It is primarily intended to
/// be used by services that cannot easily depend on the generic manager.
/// </remarks>
public interface IOpenIddictApplicationManager
{

6
src/OpenIddict.Abstractions/Managers/IOpenIddictAuthorizationManager.cs

@ -15,10 +15,8 @@ namespace OpenIddict.Abstractions;
/// </summary>
/// <remarks>
/// Note: this interface is not meant to be implemented by custom managers,
/// that should inherit from the generic OpenIddictAuthorizationManager class.
/// It is primarily intended to be used by services that cannot easily depend
/// on the generic authorization manager. The actual authorization entity type
/// is automatically determined at runtime based on the OpenIddict core options.
/// that should inherit from the generic class. It is primarily intended to
/// be used by services that cannot easily depend on the generic manager.
/// </remarks>
public interface IOpenIddictAuthorizationManager
{

8
src/OpenIddict.Abstractions/Managers/IOpenIddictResourceManager.cs

@ -12,14 +12,12 @@ using System.Text.Json;
namespace OpenIddict.Abstractions;
/// <summary>
/// Provides methods allowing to manage the Resources stored in the store.
/// Provides methods allowing to manage the resources stored in the store.
/// </summary>
/// <remarks>
/// Note: this interface is not meant to be implemented by custom managers,
/// that should inherit from the generic OpenIddictResourceManager class.
/// It is primarily intended to be used by services that cannot easily
/// depend on the generic resource manager. The actual resource entity type is
/// automatically determined at runtime based on the OpenIddict core options.
/// that should inherit from the generic class. It is primarily intended to
/// be used by services that cannot easily depend on the generic manager.
/// </remarks>
public interface IOpenIddictResourceManager
{

6
src/OpenIddict.Abstractions/Managers/IOpenIddictScopeManager.cs

@ -16,10 +16,8 @@ namespace OpenIddict.Abstractions;
/// </summary>
/// <remarks>
/// Note: this interface is not meant to be implemented by custom managers,
/// that should inherit from the generic OpenIddictScopeManager class.
/// It is primarily intended to be used by services that cannot easily
/// depend on the generic scope manager. The actual scope entity type is
/// automatically determined at runtime based on the OpenIddict core options.
/// that should inherit from the generic class. It is primarily intended to
/// be used by services that cannot easily depend on the generic manager.
/// </remarks>
public interface IOpenIddictScopeManager
{

8
src/OpenIddict.Abstractions/Managers/IOpenIddictSessionManager.cs

@ -11,14 +11,12 @@ using System.Text.Json;
namespace OpenIddict.Abstractions;
/// <summary>
/// Provides methods allowing to manage the Sessions stored in the store.
/// Provides methods allowing to manage the sessions stored in the store.
/// </summary>
/// <remarks>
/// Note: this interface is not meant to be implemented by custom managers,
/// that should inherit from the generic OpenIddictSessionManager class.
/// It is primarily intended to be used by services that cannot easily
/// depend on the generic session manager. The actual session entity type is
/// automatically determined at runtime based on the OpenIddict core options.
/// that should inherit from the generic class. It is primarily intended to
/// be used by services that cannot easily depend on the generic manager.
/// </remarks>
public interface IOpenIddictSessionManager
{

6
src/OpenIddict.Abstractions/Managers/IOpenIddictTokenManager.cs

@ -15,10 +15,8 @@ namespace OpenIddict.Abstractions;
/// </summary>
/// <remarks>
/// Note: this interface is not meant to be implemented by custom managers,
/// that should inherit from the generic OpenIddictTokenManager class.
/// It is primarily intended to be used by services that cannot easily
/// depend on the generic token manager. The actual token entity type is
/// automatically determined at runtime based on the OpenIddict core options.
/// that should inherit from the generic class. It is primarily intended to
/// be used by services that cannot easily depend on the generic manager.
/// </remarks>
public interface IOpenIddictTokenManager
{

1
src/OpenIddict.Core/Managers/OpenIddictResourceManager.cs

@ -12,7 +12,6 @@ using System.Text;
using System.Text.Json;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using static System.Net.Mime.MediaTypeNames;
using ValidationException = OpenIddict.Abstractions.OpenIddictExceptions.ValidationException;
namespace OpenIddict.Core;

49
src/OpenIddict.EntityFramework/OpenIddictEntityFrameworkHelpers.cs

@ -4,9 +4,7 @@
* the license and the contributors participating to this project.
*/
using System.Data.Entity.Infrastructure;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using Microsoft.Extensions.DependencyInjection;
using OpenIddict.EntityFramework;
using OpenIddict.EntityFramework.Models;
@ -70,51 +68,4 @@ public static class OpenIddictEntityFrameworkHelpers
return builder;
}
/// <summary>
/// Executes the query and returns the results as a streamed async enumeration.
/// </summary>
/// <typeparam name="T">The type of the returned entities.</typeparam>
/// <param name="source">The query source.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
/// <returns>The streamed async enumeration containing the results.</returns>
#pragma warning disable MA0156
internal static IAsyncEnumerable<T> AsAsyncEnumerable<T>(this IQueryable<T> source, CancellationToken cancellationToken)
#pragma warning restore MA0156
{
ArgumentNullException.ThrowIfNull(source);
return ExecuteAsync(source, cancellationToken);
static async IAsyncEnumerable<T> ExecuteAsync(IQueryable<T> source, [EnumeratorCancellation] CancellationToken cancellationToken)
{
using var enumerator = ((IDbAsyncEnumerable<T>) source).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return enumerator.Current;
}
}
}
/// <summary>
/// Tries to create a new <see cref="DbContextTransaction"/> with the specified <paramref name="level"/>.
/// </summary>
/// <param name="context">The Entity Framework context.</param>
/// <param name="level">The desired level of isolation.</param>
/// <returns>The <see cref="DbContextTransaction"/> if it could be created, <see langword="null"/> otherwise.</returns>
internal static DbContextTransaction? CreateTransaction(this DbContext context, IsolationLevel level)
{
ArgumentNullException.ThrowIfNull(context);
try
{
return context.Database.BeginTransaction(level);
}
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
return null;
}
}
}

67
src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkApplicationStore.cs

@ -121,7 +121,7 @@ public class OpenIddictEntityFrameworkApplicationStore<
var context = await Context.GetDbContextAsync(cancellationToken);
Task<List<TAuthorization>> ListAuthorizationsAsync()
=> (from authorization in context.Set<TAuthorization>().Include(authorization => authorization.Tokens)
=> (from authorization in context.Set<TAuthorization>().Include(static authorization => authorization.Tokens)
where authorization.Application!.Id!.Equals(application.Id)
select authorization).ToListAsync(cancellationToken);
@ -134,7 +134,7 @@ public class OpenIddictEntityFrameworkApplicationStore<
// To prevent an SQL exception from being thrown if a new associated entity is
// created after the existing entries have been listed, the following logic is
// executed in a serializable transaction, that will lock the affected tables.
using var transaction = context.CreateTransaction(IsolationLevel.Serializable);
using var transaction = CreateTransaction(context, IsolationLevel.Serializable);
// Remove all the authorizations associated with the application and
// the tokens attached to these implicit or explicit authorizations.
@ -237,16 +237,18 @@ public class OpenIddictEntityFrameworkApplicationStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
var applications = (from application in context.Set<TApplication>()
where application.PostLogoutRedirectUris!.Contains(uri)
select application).AsAsyncEnumerable(cancellationToken);
var applications = from application in context.Set<TApplication>()
where application.PostLogoutRedirectUris!.Contains(uri)
select application;
await foreach (var application in applications.WithCancellation(cancellationToken))
using var enumerator = ((IDbAsyncEnumerable<TApplication>) applications).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
var uris = await GetPostLogoutRedirectUrisAsync(application, cancellationToken);
var uris = await GetPostLogoutRedirectUrisAsync(enumerator.Current, cancellationToken);
if (uris.Contains(uri, StringComparer.Ordinal))
{
yield return application;
yield return enumerator.Current;
}
}
}
@ -270,16 +272,18 @@ public class OpenIddictEntityFrameworkApplicationStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
var applications = (from application in context.Set<TApplication>()
where application.RedirectUris!.Contains(uri)
select application).AsAsyncEnumerable(cancellationToken);
var applications = from application in context.Set<TApplication>()
where application.RedirectUris!.Contains(uri)
select application;
using var enumerator = ((IDbAsyncEnumerable<TApplication>) applications).GetAsyncEnumerator();
await foreach (var application in applications.WithCancellation(cancellationToken))
while (await enumerator.MoveNextAsync(cancellationToken))
{
var uris = await GetRedirectUrisAsync(application, cancellationToken);
var uris = await GetRedirectUrisAsync(enumerator.Current, cancellationToken);
if (uris.Contains(uri, StringComparer.Ordinal))
{
yield return application;
yield return enumerator.Current;
}
}
}
@ -658,7 +662,7 @@ public class OpenIddictEntityFrameworkApplicationStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
IQueryable<TApplication> query = context.Set<TApplication>().OrderBy(application => application.Id!);
IQueryable<TApplication> query = context.Set<TApplication>().OrderBy(static application => application.Id!);
if (offset is not null)
{
@ -670,9 +674,11 @@ public class OpenIddictEntityFrameworkApplicationStore<
query = query.Take(count.Value);
}
await foreach (var application in query.AsAsyncEnumerable(cancellationToken))
using var enumerator = ((IDbAsyncEnumerable<TApplication>) query).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return application;
yield return enumerator.Current;
}
}
@ -689,9 +695,11 @@ public class OpenIddictEntityFrameworkApplicationStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
await foreach (var application in query(context.Set<TApplication>(), state).AsAsyncEnumerable(cancellationToken))
using var enumerator = ((IDbAsyncEnumerable<TResult>) query(context.Set<TApplication>(), state)).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return application;
yield return enumerator.Current;
}
}
}
@ -1097,4 +1105,25 @@ public class OpenIddictEntityFrameworkApplicationStore<
return converter.ConvertToInvariantString(identifier);
}
/// <summary>
/// Tries to create a new <see cref="DbContextTransaction"/> with the specified <paramref name="level"/>.
/// </summary>
/// <param name="context">The Entity Framework context.</param>
/// <param name="level">The desired level of isolation.</param>
/// <returns>The <see cref="DbContextTransaction"/> if it could be created, <see langword="null"/> otherwise.</returns>
protected virtual DbContextTransaction? CreateTransaction(DbContext context, IsolationLevel level)
{
ArgumentNullException.ThrowIfNull(context);
try
{
return context.Database.BeginTransaction(level);
}
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
return null;
}
}
}

109
src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkAuthorizationStore.cs

@ -126,7 +126,7 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
// To prevent an SQL exception from being thrown if a new associated entity is
// created after the existing entries have been listed, the following logic is
// executed in a serializable transaction, that will lock the affected tables.
using var transaction = context.CreateTransaction(IsolationLevel.Serializable);
using var transaction = CreateTransaction(context, IsolationLevel.Serializable);
// Remove all the tokens associated with the authorization.
var tokens = await ListTokensAsync();
@ -165,7 +165,8 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
IQueryable<TAuthorization> authorizations = context.Set<TAuthorization>().Include(authorization => authorization.Application);
IQueryable<TAuthorization> authorizations = context.Set<TAuthorization>()
.Include(static authorization => authorization.Application);
if (!string.IsNullOrEmpty(query.Subject))
{
@ -188,18 +189,20 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
authorizations = authorizations.Where(authorization => authorization.Type == query.Type);
}
using var enumerator = ((IDbAsyncEnumerable<TAuthorization>) authorizations).GetAsyncEnumerator();
// Note: Entity Framework Core cannot translate the logic used to filter authorizations by scopes in a
// SQL query so the filtering is done manually after the results have been retrieved from the database.
await foreach (var authorization in authorizations.AsAsyncEnumerable(cancellationToken))
while (await enumerator.MoveNextAsync(cancellationToken))
{
if (query.RequiredScopes is { IsDefaultOrEmpty: false } scopes && !(await GetScopesAsync(authorization, cancellationToken))
if (query.RequiredScopes is { IsDefaultOrEmpty: false } scopes && !(await GetScopesAsync(enumerator.Current, cancellationToken))
.ToHashSet(StringComparer.Ordinal)
.IsSupersetOf(scopes))
{
continue;
}
yield return authorization;
yield return enumerator.Current;
}
}
@ -215,12 +218,16 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
var context = await Context.GetDbContextAsync(cancellationToken);
var key = ConvertIdentifierFromString(identifier);
await foreach (var authorization in
(from authorization in context.Set<TAuthorization>().Include(authorization => authorization.Application)
where authorization.Application!.Id!.Equals(key)
select authorization).AsAsyncEnumerable(cancellationToken))
var authorizations = from authorization in context.Set<TAuthorization>()
.Include(static authorization => authorization.Application)
where authorization.Application!.Id!.Equals(key)
select authorization;
using var enumerator = ((IDbAsyncEnumerable<TAuthorization>) authorizations).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return authorization;
yield return enumerator.Current;
}
}
}
@ -247,12 +254,16 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
await foreach (var authorization in
(from authorization in context.Set<TAuthorization>().Include(authorization => authorization.Application)
where authorization.Subject == subject
select authorization).AsAsyncEnumerable(cancellationToken))
var authorizations = from authorization in context.Set<TAuthorization>()
.Include(static authorization => authorization.Application)
where authorization.Subject == subject
select authorization;
using var enumerator = ((IDbAsyncEnumerable<TAuthorization>) authorizations).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return authorization;
yield return enumerator.Current;
}
}
}
@ -294,7 +305,7 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
var context = await Context.GetDbContextAsync(cancellationToken);
return await query(
context.Set<TAuthorization>().Include(authorization => authorization.Application), state).FirstOrDefaultAsync(cancellationToken);
context.Set<TAuthorization>().Include(static authorization => authorization.Application), state).FirstOrDefaultAsync(cancellationToken);
}
/// <inheritdoc/>
@ -429,8 +440,8 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
var context = await Context.GetDbContextAsync(cancellationToken);
IQueryable<TAuthorization> query = context.Set<TAuthorization>()
.Include(authorization => authorization.Application)
.OrderBy(authorization => authorization.Id!);
.Include(static authorization => authorization.Application)
.OrderBy(static authorization => authorization.Id!);
if (offset is not null)
{
@ -442,9 +453,11 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
query = query.Take(count.Value);
}
await foreach (var authorization in query.AsAsyncEnumerable(cancellationToken))
using var enumerator = ((IDbAsyncEnumerable<TAuthorization>) query).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return authorization;
yield return enumerator.Current;
}
}
@ -461,11 +474,13 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
await foreach (var authorization in query(context
using var enumerator = ((IDbAsyncEnumerable<TResult>) query(context
.Set<TAuthorization>()
.Include(authorization => authorization.Application), state).AsAsyncEnumerable(cancellationToken))
.Include(static authorization => authorization.Application), state)).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return authorization;
yield return enumerator.Current;
}
}
}
@ -493,7 +508,7 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
// after it was retrieved from the database, the following logic is executed in
// a repeatable read transaction, that will put a lock on the retrieved entries
// and thus prevent them from being concurrently modified outside this block.
using var transaction = context.CreateTransaction(IsolationLevel.RepeatableRead);
using var transaction = CreateTransaction(context, IsolationLevel.RepeatableRead);
// Note: the Oracle MySQL provider doesn't support DateTimeOffset and is unable
// to create a SQL query with an expression calling DateTimeOffset.UtcDateTime.
@ -502,7 +517,7 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
var date = threshold.UtcDateTime;
var authorizations =
await (from authorization in context.Set<TAuthorization>().Include(authorization => authorization.Tokens)
await (from authorization in context.Set<TAuthorization>().Include(static authorization => authorization.Tokens)
where authorization.CreationDate < date
where authorization.Status != Statuses.Valid || authorization.Type == AuthorizationTypes.AdHoc
where !authorization.Tokens.Any()
@ -528,7 +543,7 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: 1);
exceptions.Add(exception);
continue;
@ -537,7 +552,7 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
result += authorizations.Count;
}
if (exceptions is not null)
if (exceptions is { Count: > 0 })
{
throw new AggregateException(SR.GetResourceString(SR.ID0243), exceptions);
}
@ -550,7 +565,8 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
IQueryable<TAuthorization> query = context.Set<TAuthorization>().Include(authorization => authorization.Application);
IQueryable<TAuthorization> query = context.Set<TAuthorization>()
.Include(static authorization => authorization.Application);
if (!string.IsNullOrEmpty(subject))
{
@ -592,7 +608,7 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
// Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing.
context.Entry(authorization).State = EntityState.Unchanged;
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: 1);
exceptions.Add(exception);
continue;
@ -601,7 +617,7 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
result++;
}
if (exceptions is not null)
if (exceptions is { Count: > 0 })
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}
@ -622,7 +638,7 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
var result = 0L;
foreach (var authorization in await (from authorization in context.Set<TAuthorization>()
.Include(authorization => authorization.Application)
.Include(static authorization => authorization.Application)
where authorization.Application!.Id!.Equals(key)
select authorization).ToListAsync(cancellationToken))
{
@ -638,7 +654,7 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
// Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing.
context.Entry(authorization).State = EntityState.Unchanged;
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: 1);
exceptions.Add(exception);
continue;
@ -647,7 +663,7 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
result++;
}
if (exceptions is not null)
if (exceptions is { Count: > 0 })
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}
@ -667,7 +683,7 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
var result = 0L;
foreach (var authorization in await (from authorization in context.Set<TAuthorization>()
.Include(authorization => authorization.Application)
.Include(static authorization => authorization.Application)
where authorization.Subject == subject
select authorization).ToListAsync(cancellationToken))
{
@ -683,7 +699,7 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
// Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing.
context.Entry(authorization).State = EntityState.Unchanged;
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: 1);
exceptions.Add(exception);
continue;
@ -692,7 +708,7 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
result++;
}
if (exceptions is not null)
if (exceptions is { Count: > 0 })
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}
@ -931,4 +947,25 @@ public class OpenIddictEntityFrameworkAuthorizationStore<
return converter.ConvertToInvariantString(identifier);
}
/// <summary>
/// Tries to create a new <see cref="DbContextTransaction"/> with the specified <paramref name="level"/>.
/// </summary>
/// <param name="context">The Entity Framework context.</param>
/// <param name="level">The desired level of isolation.</param>
/// <returns>The <see cref="DbContextTransaction"/> if it could be created, <see langword="null"/> otherwise.</returns>
protected virtual DbContextTransaction? CreateTransaction(DbContext context, IsolationLevel level)
{
ArgumentNullException.ThrowIfNull(context);
try
{
return context.Database.BeginTransaction(level);
}
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
return null;
}
}
}

27
src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkResourceStore.cs

@ -173,12 +173,15 @@ public class OpenIddictEntityFrameworkResourceStore<
// Note: Enumerable.Contains() is deliberately used without the extension method syntax to ensure
// ImmutableArray.Contains() (which is not fully supported by Entity Framework 6.x) is not used instead.
await foreach (var resource in
(from resource in context.Set<TResource>()
where Enumerable.Contains(names, resource.Name)
select resource).AsAsyncEnumerable(cancellationToken))
var resources = from resource in context.Set<TResource>()
where Enumerable.Contains(names, resource.Name)
select resource;
using var enumerator = ((IDbAsyncEnumerable<TResource>) resources).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return resource;
yield return enumerator.Current;
}
}
}
@ -356,7 +359,7 @@ public class OpenIddictEntityFrameworkResourceStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
IQueryable<TResource> query = context.Set<TResource>().OrderBy(resource => resource.Id!);
IQueryable<TResource> query = context.Set<TResource>().OrderBy(static resource => resource.Id!);
if (offset is not null)
{
@ -368,9 +371,11 @@ public class OpenIddictEntityFrameworkResourceStore<
query = query.Take(count.Value);
}
await foreach (var resource in query.AsAsyncEnumerable(cancellationToken))
using var enumerator = ((IDbAsyncEnumerable<TResource>) query).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return resource;
yield return enumerator.Current;
}
}
@ -387,9 +392,11 @@ public class OpenIddictEntityFrameworkResourceStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
await foreach (var resource in query(context.Set<TResource>(), state).AsAsyncEnumerable(cancellationToken))
using var enumerator = ((IDbAsyncEnumerable<TResult>) query(context.Set<TResource>(), state)).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return resource;
yield return enumerator.Current;
}
}
}

41
src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkScopeStore.cs

@ -173,12 +173,15 @@ public class OpenIddictEntityFrameworkScopeStore<
// Note: Enumerable.Contains() is deliberately used without the extension method syntax to ensure
// ImmutableArray.Contains() (which is not fully supported by Entity Framework 6.x) is not used instead.
await foreach (var scope in
(from scope in context.Set<TScope>()
where Enumerable.Contains(names, scope.Name)
select scope).AsAsyncEnumerable(cancellationToken))
var scopes = from scope in context.Set<TScope>()
where Enumerable.Contains(names, scope.Name)
select scope;
using var enumerator = ((IDbAsyncEnumerable<TScope>) scopes).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return scope;
yield return enumerator.Current;
}
}
}
@ -200,16 +203,18 @@ public class OpenIddictEntityFrameworkScopeStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
var scopes = (from scope in context.Set<TScope>()
where scope.Resources!.Contains(resource)
select scope).AsAsyncEnumerable(cancellationToken);
var scopes = from scope in context.Set<TScope>()
where scope.Resources!.Contains(resource)
select scope;
using var enumerator = ((IDbAsyncEnumerable<TScope>) scopes).GetAsyncEnumerator();
await foreach (var scope in scopes.WithCancellation(cancellationToken))
while (await enumerator.MoveNextAsync(cancellationToken))
{
var resources = await GetResourcesAsync(scope, cancellationToken);
var resources = await GetResourcesAsync(enumerator.Current, cancellationToken);
if (resources.Contains(resource, StringComparer.Ordinal))
{
yield return scope;
yield return enumerator.Current;
}
}
}
@ -426,7 +431,7 @@ public class OpenIddictEntityFrameworkScopeStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
IQueryable<TScope> query = context.Set<TScope>().OrderBy(scope => scope.Id!);
IQueryable<TScope> query = context.Set<TScope>().OrderBy(static scope => scope.Id!);
if (offset is not null)
{
@ -438,9 +443,11 @@ public class OpenIddictEntityFrameworkScopeStore<
query = query.Take(count.Value);
}
await foreach (var scope in query.AsAsyncEnumerable(cancellationToken))
using var enumerator = ((IDbAsyncEnumerable<TScope>) query).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return scope;
yield return enumerator.Current;
}
}
@ -457,9 +464,11 @@ public class OpenIddictEntityFrameworkScopeStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
await foreach (var scope in query(context.Set<TScope>(), state).AsAsyncEnumerable(cancellationToken))
using var enumerator = ((IDbAsyncEnumerable<TResult>) query(context.Set<TScope>(), state)).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return scope;
yield return enumerator.Current;
}
}
}

84
src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkSessionStore.cs

@ -145,8 +145,8 @@ public class OpenIddictEntityFrameworkSessionStore<
var context = await Context.GetDbContextAsync(cancellationToken);
IQueryable<TSession> sessions = context.Set<TSession>()
.Include(session => session.Application)
.Include(session => session.Authorization);
.Include(static session => session.Application)
.Include(static session => session.Authorization);
if (!string.IsNullOrEmpty(query.Subject))
{
@ -169,9 +169,11 @@ public class OpenIddictEntityFrameworkSessionStore<
sessions = sessions.Where(session => session.Status == query.Status);
}
await foreach (var session in sessions.AsAsyncEnumerable(cancellationToken))
using var enumerator = ((IDbAsyncEnumerable<TSession>) sessions).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return session;
yield return enumerator.Current;
}
}
@ -187,12 +189,17 @@ public class OpenIddictEntityFrameworkSessionStore<
var context = await Context.GetDbContextAsync(cancellationToken);
var key = ConvertIdentifierFromString(identifier);
await foreach (var session in
(from session in context.Set<TSession>().Include(session => session.Application).Include(session => session.Authorization)
where session.Application!.Id!.Equals(key)
select session).AsAsyncEnumerable(cancellationToken))
var sessions = from session in context.Set<TSession>()
.Include(static session => session.Application)
.Include(static session => session.Authorization)
where session.Application!.Id!.Equals(key)
select session;
using var enumerator = ((IDbAsyncEnumerable<TSession>) sessions).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return session;
yield return enumerator.Current;
}
}
}
@ -209,12 +216,17 @@ public class OpenIddictEntityFrameworkSessionStore<
var context = await Context.GetDbContextAsync(cancellationToken);
var key = ConvertIdentifierFromString(identifier);
await foreach (var session in
(from session in context.Set<TSession>().Include(session => session.Application).Include(session => session.Authorization)
where session.Authorization!.Id!.Equals(key)
select session).AsAsyncEnumerable(cancellationToken))
var sessions = from session in context.Set<TSession>()
.Include(static session => session.Application)
.Include(static session => session.Authorization)
where session.Authorization!.Id!.Equals(key)
select session;
using var enumerator = ((IDbAsyncEnumerable<TSession>) sessions).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return session;
yield return enumerator.Current;
}
}
}
@ -241,12 +253,17 @@ public class OpenIddictEntityFrameworkSessionStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
await foreach (var session in
(from session in context.Set<TSession>().Include(session => session.Application).Include(session => session.Authorization)
where session.LoginId == identifier
select session).AsAsyncEnumerable(cancellationToken))
var sessions = from session in context.Set<TSession>()
.Include(static session => session.Application)
.Include(static session => session.Authorization)
where session.LoginId == identifier
select session;
using var enumerator = ((IDbAsyncEnumerable<TSession>) sessions).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return session;
yield return enumerator.Current;
}
}
}
@ -262,12 +279,17 @@ public class OpenIddictEntityFrameworkSessionStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
await foreach (var session in
(from session in context.Set<TSession>().Include(session => session.Application).Include(session => session.Authorization)
where session.Subject == subject
select session).AsAsyncEnumerable(cancellationToken))
var sessions = from session in context.Set<TSession>()
.Include(static session => session.Application)
.Include(static session => session.Authorization)
where session.Subject == subject
select session;
using var enumerator = ((IDbAsyncEnumerable<TSession>) sessions).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return session;
yield return enumerator.Current;
}
}
}
@ -431,7 +453,7 @@ public class OpenIddictEntityFrameworkSessionStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
IQueryable<TSession> query = context.Set<TSession>().OrderBy(session => session.Id!);
IQueryable<TSession> query = context.Set<TSession>().OrderBy(static session => session.Id!);
if (offset is not null)
{
@ -443,9 +465,11 @@ public class OpenIddictEntityFrameworkSessionStore<
query = query.Take(count.Value);
}
await foreach (var session in query.AsAsyncEnumerable(cancellationToken))
using var enumerator = ((IDbAsyncEnumerable<TSession>) query).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return session;
yield return enumerator.Current;
}
}
@ -462,9 +486,11 @@ public class OpenIddictEntityFrameworkSessionStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
await foreach (var session in query(context.Set<TSession>(), state).AsAsyncEnumerable(cancellationToken))
using var enumerator = ((IDbAsyncEnumerable<TResult>) query(context.Set<TSession>(), state)).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return session;
yield return enumerator.Current;
}
}
}

146
src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkTokenStore.cs

@ -142,8 +142,8 @@ public class OpenIddictEntityFrameworkTokenStore<
var context = await Context.GetDbContextAsync(cancellationToken);
IQueryable<TToken> tokens = context.Set<TToken>()
.Include(token => token.Application)
.Include(token => token.Authorization);
.Include(static token => token.Application)
.Include(static token => token.Authorization);
if (!string.IsNullOrEmpty(query.Subject))
{
@ -166,9 +166,11 @@ public class OpenIddictEntityFrameworkTokenStore<
tokens = tokens.Where(token => token.Type == query.Type);
}
await foreach (var token in tokens.AsAsyncEnumerable(cancellationToken))
using var enumerator = ((IDbAsyncEnumerable<TToken>) tokens).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return token;
yield return enumerator.Current;
}
}
@ -184,12 +186,17 @@ public class OpenIddictEntityFrameworkTokenStore<
var context = await Context.GetDbContextAsync(cancellationToken);
var key = ConvertIdentifierFromString(identifier);
await foreach (var token in
(from token in context.Set<TToken>().Include(token => token.Application).Include(token => token.Authorization)
where token.Application!.Id!.Equals(key)
select token).AsAsyncEnumerable(cancellationToken))
var tokens = from token in context.Set<TToken>()
.Include(static token => token.Application)
.Include(static token => token.Authorization)
where token.Application!.Id!.Equals(key)
select token;
using var enumerator = ((IDbAsyncEnumerable<TToken>) tokens).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return token;
yield return enumerator.Current;
}
}
}
@ -206,12 +213,17 @@ public class OpenIddictEntityFrameworkTokenStore<
var context = await Context.GetDbContextAsync(cancellationToken);
var key = ConvertIdentifierFromString(identifier);
await foreach (var token in
(from token in context.Set<TToken>().Include(token => token.Application).Include(token => token.Authorization)
where token.Authorization!.Id!.Equals(key)
select token).AsAsyncEnumerable(cancellationToken))
var tokens = from token in context.Set<TToken>()
.Include(static token => token.Application)
.Include(static token => token.Authorization)
where token.Authorization!.Id!.Equals(key)
select token;
using var enumerator = ((IDbAsyncEnumerable<TToken>) tokens).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return token;
yield return enumerator.Current;
}
}
}
@ -242,7 +254,9 @@ public class OpenIddictEntityFrameworkTokenStore<
select entry.Entity).FirstOrDefault();
Task<TToken?> QueryAsync() =>
(from token in context.Set<TToken>().Include(token => token.Application).Include(token => token.Authorization)
(from token in context.Set<TToken>()
.Include(static token => token.Application)
.Include(static token => token.Authorization)
where token.ReferenceId == identifier
select token).FirstOrDefaultAsync(cancellationToken);
}
@ -258,12 +272,15 @@ public class OpenIddictEntityFrameworkTokenStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
await foreach (var token in
(from token in context.Set<TToken>().Include(token => token.Application).Include(token => token.Authorization)
where token.Subject == subject
select token).AsAsyncEnumerable(cancellationToken))
var tokens = from token in context.Set<TToken>().Include(token => token.Application).Include(token => token.Authorization)
where token.Subject == subject
select token;
using var enumerator = ((IDbAsyncEnumerable<TToken>) tokens).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return token;
yield return enumerator.Current;
}
}
}
@ -304,10 +321,9 @@ public class OpenIddictEntityFrameworkTokenStore<
var context = await Context.GetDbContextAsync(cancellationToken);
return await query(
context.Set<TToken>()
.Include(token => token.Application)
.Include(token => token.Authorization), state).FirstOrDefaultAsync(cancellationToken);
return await query(context.Set<TToken>()
.Include(static token => token.Application)
.Include(static token => token.Authorization), state).FirstOrDefaultAsync(cancellationToken);
}
/// <inheritdoc/>
@ -463,9 +479,9 @@ public class OpenIddictEntityFrameworkTokenStore<
var context = await Context.GetDbContextAsync(cancellationToken);
IQueryable<TToken> query = context.Set<TToken>()
.Include(token => token.Application)
.Include(token => token.Authorization)
.OrderBy(token => token.Id!);
.Include(static token => token.Application)
.Include(static token => token.Authorization)
.OrderBy(static token => token.Id!);
if (offset is not null)
{
@ -477,9 +493,11 @@ public class OpenIddictEntityFrameworkTokenStore<
query = query.Take(count.Value);
}
await foreach (var token in query.AsAsyncEnumerable(cancellationToken))
using var enumerator = ((IDbAsyncEnumerable<TToken>) query).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return token;
yield return enumerator.Current;
}
}
@ -496,12 +514,13 @@ public class OpenIddictEntityFrameworkTokenStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
await foreach (var token in query(
context.Set<TToken>()
.Include(token => token.Application)
.Include(token => token.Authorization), state).AsAsyncEnumerable(cancellationToken))
using var enumerator = ((IDbAsyncEnumerable<TResult>) query(context.Set<TToken>()
.Include(static token => token.Application)
.Include(static token => token.Authorization), state)).GetAsyncEnumerator();
while (await enumerator.MoveNextAsync(cancellationToken))
{
yield return token;
yield return enumerator.Current;
}
}
}
@ -529,7 +548,7 @@ public class OpenIddictEntityFrameworkTokenStore<
// after it was retrieved from the database, the following logic is executed in
// a repeatable read transaction, that will put a lock on the retrieved entries
// and thus prevent them from being concurrently modified outside this block.
using var transaction = context.CreateTransaction(IsolationLevel.RepeatableRead);
using var transaction = CreateTransaction(context, IsolationLevel.RepeatableRead);
// Note: the Oracle MySQL provider doesn't support DateTimeOffset and is unable
// to create a SQL query with an expression calling DateTimeOffset.UtcDateTime.
@ -561,7 +580,7 @@ public class OpenIddictEntityFrameworkTokenStore<
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: 1);
exceptions.Add(exception);
continue;
@ -570,7 +589,7 @@ public class OpenIddictEntityFrameworkTokenStore<
result += tokens.Count;
}
if (exceptions is not null)
if (exceptions is { Count: > 0 })
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}
@ -583,7 +602,9 @@ public class OpenIddictEntityFrameworkTokenStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
IQueryable<TToken> query = context.Set<TToken>().Include(token => token.Application).Include(token => token.Authorization);
IQueryable<TToken> query = context.Set<TToken>()
.Include(static token => token.Application)
.Include(static token => token.Authorization);
if (!string.IsNullOrEmpty(subject))
{
@ -625,7 +646,7 @@ public class OpenIddictEntityFrameworkTokenStore<
// Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing.
context.Entry(token).State = EntityState.Unchanged;
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: 1);
exceptions.Add(exception);
continue;
@ -634,7 +655,7 @@ public class OpenIddictEntityFrameworkTokenStore<
result++;
}
if (exceptions is not null)
if (exceptions is { Count: > 0 })
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}
@ -655,8 +676,8 @@ public class OpenIddictEntityFrameworkTokenStore<
var result = 0L;
foreach (var token in await (from token in context.Set<TToken>()
.Include(token => token.Application)
.Include(token => token.Authorization)
.Include(static token => token.Application)
.Include(static token => token.Authorization)
where token.Application!.Id!.Equals(key)
where token.Status != Statuses.Revoked
select token).ToListAsync(cancellationToken))
@ -673,7 +694,7 @@ public class OpenIddictEntityFrameworkTokenStore<
// Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing.
context.Entry(token).State = EntityState.Unchanged;
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: 1);
exceptions.Add(exception);
continue;
@ -682,7 +703,7 @@ public class OpenIddictEntityFrameworkTokenStore<
result++;
}
if (exceptions is not null)
if (exceptions is { Count: > 0 })
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}
@ -703,8 +724,8 @@ public class OpenIddictEntityFrameworkTokenStore<
var result = 0L;
foreach (var token in await (from token in context.Set<TToken>()
.Include(token => token.Application)
.Include(token => token.Authorization)
.Include(static token => token.Application)
.Include(static token => token.Authorization)
where token.Authorization!.Id!.Equals(key)
where token.Status != Statuses.Revoked
select token).ToListAsync(cancellationToken))
@ -721,7 +742,7 @@ public class OpenIddictEntityFrameworkTokenStore<
// Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing.
context.Entry(token).State = EntityState.Unchanged;
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: 1);
exceptions.Add(exception);
continue;
@ -730,7 +751,7 @@ public class OpenIddictEntityFrameworkTokenStore<
result++;
}
if (exceptions is not null)
if (exceptions is { Count: > 0 })
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}
@ -750,8 +771,8 @@ public class OpenIddictEntityFrameworkTokenStore<
var result = 0L;
foreach (var token in await (from token in context.Set<TToken>()
.Include(token => token.Application)
.Include(token => token.Authorization)
.Include(static token => token.Application)
.Include(static token => token.Authorization)
where token.Subject == subject
where token.Status != Statuses.Revoked
select token).ToListAsync(cancellationToken))
@ -768,7 +789,7 @@ public class OpenIddictEntityFrameworkTokenStore<
// Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing.
context.Entry(token).State = EntityState.Unchanged;
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: 1);
exceptions.Add(exception);
continue;
@ -777,7 +798,7 @@ public class OpenIddictEntityFrameworkTokenStore<
result++;
}
if (exceptions is not null)
if (exceptions is { Count: > 0 })
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}
@ -1053,4 +1074,25 @@ public class OpenIddictEntityFrameworkTokenStore<
return converter.ConvertToInvariantString(identifier);
}
/// <summary>
/// Tries to create a new <see cref="DbContextTransaction"/> with the specified <paramref name="level"/>.
/// </summary>
/// <param name="context">The Entity Framework context.</param>
/// <param name="level">The desired level of isolation.</param>
/// <returns>The <see cref="DbContextTransaction"/> if it could be created, <see langword="null"/> otherwise.</returns>
protected virtual DbContextTransaction? CreateTransaction(DbContext context, IsolationLevel level)
{
ArgumentNullException.ThrowIfNull(context);
try
{
return context.Database.BeginTransaction(level);
}
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
return null;
}
}
}

6
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreApplicationStore.cs

@ -187,7 +187,9 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<
// Remove all the authorizations associated with the application and
// the tokens attached to these implicit or explicit authorizations.
var authorizations = await (
from authorization in context.Set<TAuthorization>().Include(authorization => authorization.Tokens).AsTracking()
from authorization in context.Set<TAuthorization>()
.Include(static authorization => authorization.Tokens)
.AsTracking()
where authorization.Application!.Id!.Equals(application.Id)
select authorization).ToListAsync(cancellationToken);
@ -481,7 +483,7 @@ public class OpenIddictEntityFrameworkCoreApplicationStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
var query = context.Set<TApplication>().OrderBy(application => application.Id!).AsTracking();
var query = context.Set<TApplication>().OrderBy(static application => application.Id!).AsTracking();
if (offset is not null)
{

61
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreAuthorizationStore.cs

@ -223,7 +223,9 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
IQueryable<TAuthorization> authorizations = context.Set<TAuthorization>().Include(authorization => authorization.Application).AsTracking();
IQueryable<TAuthorization> authorizations = context.Set<TAuthorization>()
.Include(static authorization => authorization.Application)
.AsTracking();
if (!string.IsNullOrEmpty(query.Subject))
{
@ -274,7 +276,9 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<
var key = ConvertIdentifierFromString(identifier);
await foreach (var authorization in
(from authorization in context.Set<TAuthorization>().Include(authorization => authorization.Application).AsTracking()
(from authorization in context.Set<TAuthorization>()
.Include(static authorization => authorization.Application)
.AsTracking()
where authorization.Application!.Id!.Equals(key)
select authorization).AsAsyncEnumerable().WithCancellation(cancellationToken))
{
@ -306,7 +310,9 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<
var context = await Context.GetDbContextAsync(cancellationToken);
await foreach (var authorization in
(from authorization in context.Set<TAuthorization>().Include(authorization => authorization.Application).AsTracking()
(from authorization in context.Set<TAuthorization>()
.Include(static authorization => authorization.Application)
.AsTracking()
where authorization.Subject == subject
select authorization).AsAsyncEnumerable().WithCancellation(cancellationToken))
{
@ -351,9 +357,9 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<
var context = await Context.GetDbContextAsync(cancellationToken);
return await query(
context.Set<TAuthorization>().Include(authorization => authorization.Application)
.AsTracking(), state).FirstOrDefaultAsync(cancellationToken);
return await query(context.Set<TAuthorization>()
.Include(static authorization => authorization.Application)
.AsTracking(), state).FirstOrDefaultAsync(cancellationToken);
}
/// <inheritdoc/>
@ -434,9 +440,9 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<
var context = await Context.GetDbContextAsync(cancellationToken);
var query = context.Set<TAuthorization>()
.Include(authorization => authorization.Application)
.OrderBy(authorization => authorization.Id!)
.AsTracking();
.Include(static authorization => authorization.Application)
.OrderBy(static authorization => authorization.Id!)
.AsTracking();
if (offset is not null)
{
@ -467,10 +473,9 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
await foreach (var authorization in query(
context.Set<TAuthorization>()
.Include(authorization => authorization.Application)
.AsTracking(), state).AsAsyncEnumerable().WithCancellation(cancellationToken))
await foreach (var authorization in query(context.Set<TAuthorization>()
.Include(static authorization => authorization.Application)
.AsTracking(), state).AsAsyncEnumerable().WithCancellation(cancellationToken))
{
yield return authorization;
}
@ -541,7 +546,9 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<
IsolationLevel.RepeatableRead, cancellationToken);
var authorizations = await
(from authorization in context.Set<TAuthorization>().Include(authorization => authorization.Tokens).AsTracking()
(from authorization in context.Set<TAuthorization>()
.Include(static authorization => authorization.Tokens)
.AsTracking()
where authorization.CreationDate < date
where authorization.Status != Statuses.Valid || authorization.Type == AuthorizationTypes.AdHoc
where !authorization.Tokens.Any()
@ -568,7 +575,7 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: 1);
exceptions.Add(exception);
}
}
@ -585,7 +592,7 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<
}
}
if (exceptions is not null)
if (exceptions is { Count: > 0 })
{
throw new AggregateException(SR.GetResourceString(SR.ID0243), exceptions);
}
@ -599,7 +606,7 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<
var context = await Context.GetDbContextAsync(cancellationToken);
IQueryable<TAuthorization> query = Options.CurrentValue.DisableBulkOperations
? context.Set<TAuthorization>().Include(authorization => authorization.Application).AsTracking()
? context.Set<TAuthorization>().Include(static authorization => authorization.Application).AsTracking()
: context.Set<TAuthorization>();
if (!string.IsNullOrEmpty(subject))
@ -651,7 +658,7 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<
// Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing.
context.Entry(authorization).State = EntityState.Unchanged;
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: 1);
exceptions.Add(exception);
continue;
@ -660,7 +667,7 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<
result++;
}
if (exceptions is not null)
if (exceptions is { Count: > 0 })
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}
@ -692,7 +699,9 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<
var result = 0L;
foreach (var authorization in await (from authorization in context.Set<TAuthorization>().Include(authorization => authorization.Application).AsTracking()
foreach (var authorization in await (from authorization in context.Set<TAuthorization>()
.Include(static authorization => authorization.Application)
.AsTracking()
where authorization.Application!.Id!.Equals(key)
select authorization).ToListAsync(cancellationToken))
{
@ -708,7 +717,7 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<
// Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing.
context.Entry(authorization).State = EntityState.Unchanged;
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: 1);
exceptions.Add(exception);
continue;
@ -717,7 +726,7 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<
result++;
}
if (exceptions is not null)
if (exceptions is { Count: > 0 })
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}
@ -749,8 +758,8 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<
var result = 0L;
foreach (var authorization in await (from authorization in context.Set<TAuthorization>()
.Include(authorization => authorization.Application)
.AsTracking()
.Include(static authorization => authorization.Application)
.AsTracking()
where authorization.Subject == subject
select authorization).ToListAsync(cancellationToken))
{
@ -766,7 +775,7 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<
// Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing.
context.Entry(authorization).State = EntityState.Unchanged;
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: 1);
exceptions.Add(exception);
continue;
@ -775,7 +784,7 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<
result++;
}
if (exceptions is not null)
if (exceptions is { Count: > 0 })
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}

2
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreResourceStore.cs

@ -279,7 +279,7 @@ public class OpenIddictEntityFrameworkCoreResourceStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
var query = context.Set<TResource>().OrderBy(resource => resource.Id!).AsTracking();
var query = context.Set<TResource>().OrderBy(static resource => resource.Id!).AsTracking();
if (offset is not null)
{

2
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreScopeStore.cs

@ -307,7 +307,7 @@ public class OpenIddictEntityFrameworkCoreScopeStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
var query = context.Set<TScope>().OrderBy(scope => scope.Id!).AsTracking();
var query = context.Set<TScope>().OrderBy(static scope => scope.Id!).AsTracking();
if (offset is not null)
{

32
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreSessionStore.cs

@ -153,9 +153,9 @@ public class OpenIddictEntityFrameworkCoreSessionStore<
var context = await Context.GetDbContextAsync(cancellationToken);
IQueryable<TSession> sessions = context.Set<TSession>()
.Include(session => session.Application)
.Include(session => session.Authorization)
.AsTracking();
.Include(static session => session.Application)
.Include(static session => session.Authorization)
.AsTracking();
if (!string.IsNullOrEmpty(query.Subject))
{
@ -198,9 +198,9 @@ public class OpenIddictEntityFrameworkCoreSessionStore<
await foreach (var session in
(from session in context.Set<TSession>()
.Include(session => session.Application)
.Include(session => session.Authorization)
.AsTracking()
.Include(static session => session.Application)
.Include(static session => session.Authorization)
.AsTracking()
where session.Application!.Id!.Equals(key)
select session).AsAsyncEnumerable().WithCancellation(cancellationToken))
{
@ -223,9 +223,9 @@ public class OpenIddictEntityFrameworkCoreSessionStore<
await foreach (var session in
(from session in context.Set<TSession>()
.Include(session => session.Application)
.Include(session => session.Authorization)
.AsTracking()
.Include(static session => session.Application)
.Include(static session => session.Authorization)
.AsTracking()
where session.Authorization!.Id!.Equals(key)
select session).AsAsyncEnumerable().WithCancellation(cancellationToken))
{
@ -258,9 +258,9 @@ public class OpenIddictEntityFrameworkCoreSessionStore<
await foreach (var session in
(from session in context.Set<TSession>()
.Include(session => session.Application)
.Include(session => session.Authorization)
.AsTracking()
.Include(static session => session.Application)
.Include(static session => session.Authorization)
.AsTracking()
where session.LoginId == identifier
select session).AsAsyncEnumerable().WithCancellation(cancellationToken))
{
@ -282,9 +282,9 @@ public class OpenIddictEntityFrameworkCoreSessionStore<
await foreach (var session in
(from session in context.Set<TSession>()
.Include(session => session.Application)
.Include(session => session.Authorization)
.AsTracking()
.Include(static session => session.Application)
.Include(static session => session.Authorization)
.AsTracking()
where session.Subject == subject
select session).AsAsyncEnumerable().WithCancellation(cancellationToken))
{
@ -428,7 +428,7 @@ public class OpenIddictEntityFrameworkCoreSessionStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
var query = context.Set<TSession>().OrderBy(session => session.Id!).AsTracking();
var query = context.Set<TSession>().OrderBy(static session => session.Id!).AsTracking();
if (offset is not null)
{

91
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreTokenStore.cs

@ -149,9 +149,9 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
var context = await Context.GetDbContextAsync(cancellationToken);
IQueryable<TToken> tokens = context.Set<TToken>()
.Include(token => token.Application)
.Include(token => token.Authorization)
.AsTracking();
.Include(static token => token.Application)
.Include(static token => token.Authorization)
.AsTracking();
if (!string.IsNullOrEmpty(query.Subject))
{
@ -194,9 +194,9 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
await foreach (var token in
(from token in context.Set<TToken>()
.Include(token => token.Application)
.Include(token => token.Authorization)
.AsTracking()
.Include(static token => token.Application)
.Include(static token => token.Authorization)
.AsTracking()
where token.Application!.Id!.Equals(key)
select token).AsAsyncEnumerable().WithCancellation(cancellationToken))
{
@ -219,9 +219,9 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
await foreach (var token in
(from token in context.Set<TToken>()
.Include(token => token.Application)
.Include(token => token.Authorization)
.AsTracking()
.Include(static token => token.Application)
.Include(static token => token.Authorization)
.AsTracking()
where token.Authorization!.Id!.Equals(key)
select token).AsAsyncEnumerable().WithCancellation(cancellationToken))
{
@ -256,7 +256,10 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
select entry.Entity).FirstOrDefault();
Task<TToken?> QueryAsync() =>
(from token in context.Set<TToken>().Include(token => token.Application).Include(token => token.Authorization).AsTracking()
(from token in context.Set<TToken>()
.Include(static token => token.Application)
.Include(static token => token.Authorization)
.AsTracking()
where token.ReferenceId == identifier
select token).FirstOrDefaultAsync(cancellationToken);
}
@ -274,9 +277,9 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
await foreach (var token in
(from token in context.Set<TToken>()
.Include(token => token.Application)
.Include(token => token.Authorization)
.AsTracking()
.Include(static token => token.Application)
.Include(static token => token.Authorization)
.AsTracking()
where token.Subject == subject
select token).AsAsyncEnumerable().WithCancellation(cancellationToken))
{
@ -321,8 +324,9 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
var context = await Context.GetDbContextAsync(cancellationToken);
return await query(context.Set<TToken>().Include(token => token.Application)
.Include(token => token.Authorization)
return await query(context.Set<TToken>()
.Include(static token => token.Application)
.Include(static token => token.Authorization)
.AsTracking(), state).FirstOrDefaultAsync(cancellationToken);
}
@ -455,10 +459,10 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
var context = await Context.GetDbContextAsync(cancellationToken);
var query = context.Set<TToken>()
.Include(token => token.Application)
.Include(token => token.Authorization)
.OrderBy(token => token.Id!)
.AsTracking();
.Include(static token => token.Application)
.Include(static token => token.Authorization)
.OrderBy(static token => token.Id!)
.AsTracking();
if (offset is not null)
{
@ -489,11 +493,10 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
{
var context = await Context.GetDbContextAsync(cancellationToken);
await foreach (var token in query(
context.Set<TToken>()
.Include(token => token.Application)
.Include(token => token.Authorization)
.AsTracking(), state).AsAsyncEnumerable().WithCancellation(cancellationToken))
await foreach (var token in query(context.Set<TToken>()
.Include(static token => token.Application)
.Include(static token => token.Authorization)
.AsTracking(), state).AsAsyncEnumerable().WithCancellation(cancellationToken))
{
yield return token;
}
@ -589,7 +592,7 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: 1);
exceptions.Add(exception);
}
}
@ -606,7 +609,7 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
}
}
if (exceptions is not null)
if (exceptions is { Count: > 0 })
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}
@ -620,7 +623,7 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
var context = await Context.GetDbContextAsync(cancellationToken);
IQueryable<TToken> query = Options.CurrentValue.DisableBulkOperations
? context.Set<TToken>().Include(token => token.Application).Include(token => token.Authorization).AsTracking()
? context.Set<TToken>().Include(static token => token.Application).Include(static token => token.Authorization).AsTracking()
: context.Set<TToken>();
if (!string.IsNullOrEmpty(subject))
@ -672,7 +675,7 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
// Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing.
context.Entry(token).State = EntityState.Unchanged;
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: 1);
exceptions.Add(exception);
continue;
@ -681,7 +684,7 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
result++;
}
if (exceptions is not null)
if (exceptions is { Count: > 0 })
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}
@ -715,9 +718,9 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
var result = 0L;
foreach (var token in await (from token in context.Set<TToken>()
.Include(token => token.Application)
.Include(token => token.Authorization)
.AsTracking()
.Include(static token => token.Application)
.Include(static token => token.Authorization)
.AsTracking()
where token.Application!.Id!.Equals(key)
where token.Status != Statuses.Revoked
select token).ToListAsync(cancellationToken))
@ -734,7 +737,7 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
// Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing.
context.Entry(token).State = EntityState.Unchanged;
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: 1);
exceptions.Add(exception);
continue;
@ -743,7 +746,7 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
result++;
}
if (exceptions is not null)
if (exceptions is { Count: > 0 })
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}
@ -777,9 +780,9 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
var result = 0L;
foreach (var token in await (from token in context.Set<TToken>()
.Include(token => token.Application)
.Include(token => token.Authorization)
.AsTracking()
.Include(static token => token.Application)
.Include(static token => token.Authorization)
.AsTracking()
where token.Authorization!.Id!.Equals(key)
where token.Status != Statuses.Revoked
select token).ToListAsync(cancellationToken))
@ -796,7 +799,7 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
// Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing.
context.Entry(token).State = EntityState.Unchanged;
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: 1);
exceptions.Add(exception);
continue;
@ -805,7 +808,7 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
result++;
}
if (exceptions is not null)
if (exceptions is { Count: > 0 })
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}
@ -838,9 +841,9 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
var result = 0L;
foreach (var token in await (from token in context.Set<TToken>()
.Include(token => token.Application)
.Include(token => token.Authorization)
.AsTracking()
.Include(static token => token.Application)
.Include(static token => token.Authorization)
.AsTracking()
where token.Subject == subject
where token.Status != Statuses.Revoked
select token).ToListAsync(cancellationToken))
@ -857,7 +860,7 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
// Reset the state of the entity to prevents future calls to SaveChangesAsync() from failing.
context.Entry(token).State = EntityState.Unchanged;
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: 1);
exceptions.Add(exception);
continue;
@ -866,7 +869,7 @@ public class OpenIddictEntityFrameworkCoreTokenStore<
result++;
}
if (exceptions is not null)
if (exceptions is { Count: > 0 })
{
throw new AggregateException(SR.GetResourceString(SR.ID0249), exceptions);
}

2
src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbApplicationStore.cs

@ -352,7 +352,7 @@ public class OpenIddictMongoDbApplicationStore<
var database = await Context.GetDatabaseAsync(cancellationToken);
var collection = database.GetCollection<TApplication>(Options.CurrentValue.ApplicationsCollectionName);
var query = (IQueryable<TApplication>) collection.AsQueryable().OrderBy(application => application.Id);
var query = (IQueryable<TApplication>) collection.AsQueryable().OrderBy(static application => application.Id);
if (offset is not null)
{

2
src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbAuthorizationStore.cs

@ -315,7 +315,7 @@ public class OpenIddictMongoDbAuthorizationStore<
var database = await Context.GetDatabaseAsync(cancellationToken);
var collection = database.GetCollection<TAuthorization>(Options.CurrentValue.AuthorizationsCollectionName);
var query = (IQueryable<TAuthorization>) collection.AsQueryable().OrderBy(authorization => authorization.Id);
var query = (IQueryable<TAuthorization>) collection.AsQueryable().OrderBy(static authorization => authorization.Id);
if (offset is not null)
{

2
src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbResourceStore.cs

@ -257,7 +257,7 @@ public class OpenIddictMongoDbResourceStore<
var database = await Context.GetDatabaseAsync(cancellationToken);
var collection = database.GetCollection<TResource>(Options.CurrentValue.ResourcesCollectionName);
var query = (IQueryable<TResource>) collection.AsQueryable().OrderBy(resource => resource.Id);
var query = (IQueryable<TResource>) collection.AsQueryable().OrderBy(static resource => resource.Id);
if (offset is not null)
{

2
src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbScopeStore.cs

@ -284,7 +284,7 @@ public class OpenIddictMongoDbScopeStore<
var database = await Context.GetDatabaseAsync(cancellationToken);
var collection = database.GetCollection<TScope>(Options.CurrentValue.ScopesCollectionName);
var query = (IQueryable<TScope>) collection.AsQueryable().OrderBy(scope => scope.Id);
var query = (IQueryable<TScope>) collection.AsQueryable().OrderBy(static scope => scope.Id);
if (offset is not null)
{

2
src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbSessionStore.cs

@ -341,7 +341,7 @@ public class OpenIddictMongoDbSessionStore<
var database = await Context.GetDatabaseAsync(cancellationToken);
var collection = database.GetCollection<TSession>(Options.CurrentValue.SessionsCollectionName);
var query = (IQueryable<TSession>) collection.AsQueryable().OrderBy(session => session.Id);
var query = (IQueryable<TSession>) collection.AsQueryable().OrderBy(static session => session.Id);
if (offset is not null)
{

2
src/OpenIddict.MongoDb/Stores/OpenIddictMongoDbTokenStore.cs

@ -365,7 +365,7 @@ public class OpenIddictMongoDbTokenStore<
var database = await Context.GetDatabaseAsync(cancellationToken);
var collection = database.GetCollection<TToken>(Options.CurrentValue.TokensCollectionName);
var query = (IQueryable<TToken>) collection.AsQueryable().OrderBy(token => token.Id);
var query = (IQueryable<TToken>) collection.AsQueryable().OrderBy(static token => token.Id);
if (offset is not null)
{

10
src/OpenIddict.Quartz/OpenIddictQuartzJob.cs

@ -88,7 +88,7 @@ public sealed class OpenIddictQuartzJob : IJob
// occurred while trying to prune the entities. In this case, add the inner exceptions to the collection.
catch (AggregateException exception) when (!OpenIddictHelpers.IsFatal(exception))
{
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: exception.InnerExceptions.Count);
exceptions.AddRange(exception.InnerExceptions);
}
@ -96,7 +96,7 @@ public sealed class OpenIddictQuartzJob : IJob
// to be re-thrown later (typically, at the very end of this job, as an AggregateException).
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: 1);
exceptions.Add(exception);
}
}
@ -133,7 +133,7 @@ public sealed class OpenIddictQuartzJob : IJob
// occurred while trying to prune the entities. In this case, add the inner exceptions to the collection.
catch (AggregateException exception) when (!OpenIddictHelpers.IsFatal(exception))
{
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: exception.InnerExceptions.Count);
exceptions.AddRange(exception.InnerExceptions);
}
@ -141,12 +141,12 @@ public sealed class OpenIddictQuartzJob : IJob
// to be re-thrown later (typically, at the very end of this job, as an AggregateException).
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
exceptions ??= [];
exceptions ??= new List<Exception>(capacity: 1);
exceptions.Add(exception);
}
}
if (exceptions is not null)
if (exceptions is { Count: > 0 })
{
throw new JobExecutionException(new AggregateException(exceptions))
{

Loading…
Cancel
Save