diff --git a/src/OpenIddict.EntityFrameworkCore/OpenIddictEntityFrameworkCoreHelpers.cs b/src/OpenIddict.EntityFrameworkCore/OpenIddictEntityFrameworkCoreHelpers.cs
index ba00bb4d..bc1bc93e 100644
--- a/src/OpenIddict.EntityFrameworkCore/OpenIddictEntityFrameworkCoreHelpers.cs
+++ b/src/OpenIddict.EntityFrameworkCore/OpenIddictEntityFrameworkCoreHelpers.cs
@@ -10,7 +10,6 @@ using System.Linq;
using System.Threading;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Query;
using OpenIddict.EntityFrameworkCore;
using OpenIddict.EntityFrameworkCore.Models;
@@ -118,27 +117,6 @@ namespace Microsoft.EntityFrameworkCore
}
#if !SUPPORTS_BCL_ASYNC_ENUMERABLE
- ///
- /// Converts an EF Core/IX-based async enumeration to a BCL enumeration.
- ///
- /// The type of the returned entities.
- /// The EF Core/IX async enumeration.
- /// The that can be used to abort the operation.
- /// The non-streamed async enumeration containing the results.
- internal static IAsyncEnumerable AsAsyncEnumerable(
- [NotNull] this AsyncEnumerable source, CancellationToken cancellationToken = default)
- {
- return ExecuteAsync(cancellationToken);
-
- async IAsyncEnumerable ExecuteAsync(CancellationToken cancellationToken)
- {
- foreach (var element in await source.ToListAsync(cancellationToken))
- {
- yield return element;
- }
- }
- }
-
///
/// Executes the query and returns the results as a non-streamed async enumeration.
///
diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictApplicationStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictApplicationStore.cs
index c0ba3477..fcc8e467 100644
--- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictApplicationStore.cs
+++ b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictApplicationStore.cs
@@ -16,7 +16,6 @@ using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
@@ -268,15 +267,6 @@ namespace OpenIddict.EntityFrameworkCore
}
}
- ///
- /// Exposes a compiled query allowing to retrieve an application using its client identifier.
- ///
- private static readonly Func> FindByClientId =
- EF.CompileAsyncQuery((TContext context, string identifier) =>
- (from application in context.Set().AsTracking()
- where application.ClientId == identifier
- select application).FirstOrDefault());
-
///
/// Retrieves an application using its client identifier.
///
@@ -286,25 +276,18 @@ namespace OpenIddict.EntityFrameworkCore
/// A that can be used to monitor the asynchronous operation,
/// whose result returns the client application corresponding to the identifier.
///
- public virtual ValueTask FindByClientIdAsync([NotNull] string identifier, CancellationToken cancellationToken)
+ public virtual async ValueTask FindByClientIdAsync([NotNull] string identifier, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(identifier))
{
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier));
}
- return new ValueTask(FindByClientId(Context, identifier));
+ return await (from application in Applications.AsTracking()
+ where application.ClientId == identifier
+ select application).FirstOrDefaultAsync(cancellationToken);
}
- ///
- /// Exposes a compiled query allowing to retrieve an application using its unique identifier.
- ///
- private static readonly Func> FindById =
- EF.CompileAsyncQuery((TContext context, TKey identifier) =>
- (from application in context.Set().AsTracking()
- where application.Id.Equals(identifier)
- select application).FirstOrDefault());
-
///
/// Retrieves an application using its unique identifier.
///
@@ -314,37 +297,19 @@ namespace OpenIddict.EntityFrameworkCore
/// A that can be used to monitor the asynchronous operation,
/// whose result returns the client application corresponding to the identifier.
///
- public virtual ValueTask FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken)
+ public virtual async ValueTask FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(identifier))
{
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier));
}
- return new ValueTask(FindById(Context, ConvertIdentifierFromString(identifier)));
- }
+ var key = ConvertIdentifierFromString(identifier);
- ///
- /// Exposes a compiled query allowing to retrieve all the applications
- /// associated with the specified post_logout_redirect_uri.
- ///
- private static readonly
-#if SUPPORTS_BCL_ASYNC_ENUMERABLE
- Func>
-#else
- Func>
-#endif
- FindByPostLogoutRedirectUri =
-
- // To optimize the efficiency of the query a bit, only applications whose stringified
- // PostLogoutRedirectUris contains the specified URL are returned. Once the applications
- // are retrieved, a second pass is made to ensure only valid elements are returned.
- // Implementers that use this query in a hot path may want to override this method
- // to use SQL Server 2016 functions like JSON_VALUE to make the query more efficient.
- EF.CompileAsyncQuery((TContext context, string address) =>
- from application in context.Set().AsTracking()
- where application.PostLogoutRedirectUris.Contains(address)
- select application);
+ return await (from application in Applications.AsTracking()
+ where application.Id.Equals(key)
+ select application).FirstOrDefaultAsync(cancellationToken);
+ }
///
/// Retrieves all the applications associated with the specified post_logout_redirect_uri.
@@ -360,35 +325,18 @@ namespace OpenIddict.EntityFrameworkCore
throw new ArgumentException("The address cannot be null or empty.", nameof(address));
}
- return FindByPostLogoutRedirectUri(Context, address)
-#if !SUPPORTS_BCL_ASYNC_ENUMERABLE
- .AsAsyncEnumerable(cancellationToken)
-#endif
- .WhereAwait(async application => (await GetPostLogoutRedirectUrisAsync(application, cancellationToken))
- .Contains(address, StringComparer.Ordinal));
- }
-
- ///
- /// Exposes a compiled query allowing to retrieve all the
- /// applications associated with the specified redirect_uri.
- ///
- private static readonly
-#if SUPPORTS_BCL_ASYNC_ENUMERABLE
- Func>
-#else
- Func>
-#endif
- FindByRedirectUri =
-
// To optimize the efficiency of the query a bit, only applications whose stringified
- // RedirectUris property contains the specified URL are returned. Once the applications
+ // PostLogoutRedirectUris contains the specified URL are returned. Once the applications
// are retrieved, a second pass is made to ensure only valid elements are returned.
- // Implementers that use this query in a hot path may want to override this method
+ // Implementers that use this method in a hot path may want to override this method
// to use SQL Server 2016 functions like JSON_VALUE to make the query more efficient.
- EF.CompileAsyncQuery((TContext context, string address) =>
- from application in context.Set().AsTracking()
- where application.RedirectUris.Contains(address)
- select application);
+ var applications = (from application in Applications.AsTracking()
+ where application.PostLogoutRedirectUris.Contains(address)
+ select application).AsAsyncEnumerable();
+
+ return applications.WhereAwait(async application =>
+ (await GetPostLogoutRedirectUrisAsync(application, cancellationToken)).Contains(address, StringComparer.Ordinal));
+ }
///
/// Retrieves all the applications associated with the specified redirect_uri.
@@ -404,12 +352,17 @@ namespace OpenIddict.EntityFrameworkCore
throw new ArgumentException("The address cannot be null or empty.", nameof(address));
}
- return FindByRedirectUri(Context, address)
-#if !SUPPORTS_BCL_ASYNC_ENUMERABLE
- .AsAsyncEnumerable(cancellationToken)
-#endif
- .WhereAwait(async application => (await GetRedirectUrisAsync(application, cancellationToken))
- .Contains(address, StringComparer.Ordinal));
+ // To optimize the efficiency of the query a bit, only applications whose stringified
+ // RedirectUris property contains the specified URL are returned. Once the applications
+ // are retrieved, a second pass is made to ensure only valid elements are returned.
+ // Implementers that use this method in a hot path may want to override this method
+ // to use SQL Server 2016 functions like JSON_VALUE to make the query more efficient.
+ var applications = (from application in Applications.AsTracking()
+ where application.RedirectUris.Contains(address)
+ select application).AsAsyncEnumerable();
+
+ return applications.WhereAwait(async application =>
+ (await GetRedirectUrisAsync(application, cancellationToken)).Contains(address, StringComparer.Ordinal));
}
///
diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs
index 2d609471..2262df29 100644
--- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs
+++ b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs
@@ -16,7 +16,6 @@ using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
@@ -244,31 +243,6 @@ namespace OpenIddict.EntityFrameworkCore
}
}
- ///
- /// Exposes a compiled query allowing to retrieve the authorizations corresponding
- /// to the specified subject and associated with the application identifier.
- ///
- private static readonly
-#if SUPPORTS_BCL_ASYNC_ENUMERABLE
- Func>
-#else
- Func>
-#endif
- FindBySubjectAndClient =
-
- // Note: due to a bug in Entity Framework Core's query visitor, the authorizations can't be
- // filtered using authorization.Application.Id.Equals(key). To work around this issue,
- // this compiled query uses an explicit join before applying the equality check.
- // See https://github.com/openiddict/openiddict-core/issues/499 for more information.
- EF.CompileAsyncQuery((TContext context, TKey identifier, string subject) =>
- from authorization in context.Set()
- .Include(authorization => authorization.Application)
- .AsTracking()
- where authorization.Subject == subject
- join application in context.Set().AsTracking() on authorization.Application.Id equals application.Id
- where application.Id.Equals(identifier)
- select authorization);
-
///
/// Retrieves the authorizations corresponding to the specified
/// subject and associated with the application identifier.
@@ -290,36 +264,19 @@ namespace OpenIddict.EntityFrameworkCore
throw new ArgumentException("The client cannot be null or empty.", nameof(client));
}
- return FindBySubjectAndClient(Context, ConvertIdentifierFromString(client), subject)
-#if !SUPPORTS_BCL_ASYNC_ENUMERABLE
- .AsAsyncEnumerable(cancellationToken)
-#endif
- ;
- }
-
- ///
- /// Exposes a compiled query allowing to retrieve the authorizations matching the specified parameters.
- ///
- private static readonly
-#if SUPPORTS_BCL_ASYNC_ENUMERABLE
- Func>
-#else
- Func>
-#endif
- FindBySubjectClientAndStatus =
-
// Note: due to a bug in Entity Framework Core's query visitor, the authorizations can't be
// filtered using authorization.Application.Id.Equals(key). To work around this issue,
- // this compiled query uses an explicit join before applying the equality check.
+ // this method is overriden to use an explicit join before applying the equality check.
// See https://github.com/openiddict/openiddict-core/issues/499 for more information.
- EF.CompileAsyncQuery((TContext context, TKey identifier, string subject, string status) =>
- from authorization in context.Set()
- .Include(authorization => authorization.Application)
- .AsTracking()
- where authorization.Subject == subject && authorization.Status == status
- join application in context.Set().AsTracking() on authorization.Application.Id equals application.Id
- where application.Id.Equals(identifier)
- select authorization);
+
+ var key = ConvertIdentifierFromString(client);
+
+ return (from authorization in Authorizations.Include(authorization => authorization.Application).AsTracking()
+ where authorization.Subject == subject
+ join application in Applications.AsTracking() on authorization.Application.Id equals application.Id
+ where application.Id.Equals(key)
+ select authorization).AsAsyncEnumerable();
+ }
///
/// Retrieves the authorizations matching the specified parameters.
@@ -348,38 +305,19 @@ namespace OpenIddict.EntityFrameworkCore
throw new ArgumentException("The status cannot be null or empty.", nameof(status));
}
- return FindBySubjectClientAndStatus(Context, ConvertIdentifierFromString(client), subject, status)
-#if !SUPPORTS_BCL_ASYNC_ENUMERABLE
- .AsAsyncEnumerable(cancellationToken)
-#endif
- ;
- }
-
- ///
- /// Exposes a compiled query allowing to retrieve the authorizations matching the specified parameters.
- ///
- private static readonly
-#if SUPPORTS_BCL_ASYNC_ENUMERABLE
- Func>
-#else
- Func>
-#endif
- FindBySubjectClientStatusAndType =
-
// Note: due to a bug in Entity Framework Core's query visitor, the authorizations can't be
// filtered using authorization.Application.Id.Equals(key). To work around this issue,
- // this compiled query uses an explicit join before applying the equality check.
+ // this method is overriden to use an explicit join before applying the equality check.
// See https://github.com/openiddict/openiddict-core/issues/499 for more information.
- EF.CompileAsyncQuery((TContext context, TKey identifier, string subject, string status, string type) =>
- from authorization in context.Set()
- .Include(authorization => authorization.Application)
- .AsTracking()
- where authorization.Subject == subject &&
- authorization.Status == status &&
- authorization.Type == type
- join application in context.Set().AsTracking() on authorization.Application.Id equals application.Id
- where application.Id.Equals(identifier)
- select authorization);
+
+ var key = ConvertIdentifierFromString(client);
+
+ return (from authorization in Authorizations.Include(authorization => authorization.Application).AsTracking()
+ where authorization.Subject == subject && authorization.Status == status
+ join application in Applications.AsTracking() on authorization.Application.Id equals application.Id
+ where application.Id.Equals(key)
+ select authorization).AsAsyncEnumerable();
+ }
///
/// Retrieves the authorizations matching the specified parameters.
@@ -414,11 +352,20 @@ namespace OpenIddict.EntityFrameworkCore
throw new ArgumentException("The type cannot be null or empty.", nameof(type));
}
- return FindBySubjectClientStatusAndType(Context, ConvertIdentifierFromString(client), subject, status, type)
-#if !SUPPORTS_BCL_ASYNC_ENUMERABLE
- .AsAsyncEnumerable(cancellationToken)
-#endif
- ;
+ // Note: due to a bug in Entity Framework Core's query visitor, the authorizations can't be
+ // filtered using authorization.Application.Id.Equals(key). To work around this issue,
+ // this method is overriden to use an explicit join before applying the equality check.
+ // See https://github.com/openiddict/openiddict-core/issues/499 for more information.
+
+ var key = ConvertIdentifierFromString(client);
+
+ return (from authorization in Authorizations.Include(authorization => authorization.Application).AsTracking()
+ where authorization.Subject == subject &&
+ authorization.Status == status &&
+ authorization.Type == type
+ join application in Applications.AsTracking() on authorization.Application.Id equals application.Id
+ where application.Id.Equals(key)
+ select authorization).AsAsyncEnumerable();
}
///
@@ -439,30 +386,6 @@ namespace OpenIddict.EntityFrameworkCore
.WhereAwait(async authorization => new HashSet(
await GetScopesAsync(authorization, cancellationToken), StringComparer.Ordinal).IsSupersetOf(scopes));
- ///
- /// Exposes a compiled query allowing to retrieve the list of
- /// authorizations corresponding to the specified application identifier.
- ///
- private static readonly
-#if SUPPORTS_BCL_ASYNC_ENUMERABLE
- Func>
-#else
- Func>
-#endif
- FindByApplicationId =
-
- // Note: due to a bug in Entity Framework Core's query visitor, the authorizations can't be
- // filtered using authorization.Application.Id.Equals(key). To work around this issue,
- // this compiled query uses an explicit join before applying the equality check.
- // See https://github.com/openiddict/openiddict-core/issues/499 for more information.
- EF.CompileAsyncQuery((TContext context, TKey identifier) =>
- from authorization in context.Set()
- .Include(authorization => authorization.Application)
- .AsTracking()
- join application in context.Set().AsTracking() on authorization.Application.Id equals application.Id
- where application.Id.Equals(identifier)
- select authorization);
-
///
/// Retrieves the list of authorizations corresponding to the specified application identifier.
///
@@ -477,23 +400,18 @@ namespace OpenIddict.EntityFrameworkCore
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier));
}
- return FindByApplicationId(Context, ConvertIdentifierFromString(identifier))
-#if !SUPPORTS_BCL_ASYNC_ENUMERABLE
- .AsAsyncEnumerable(cancellationToken)
-#endif
- ;
- }
+ // Note: due to a bug in Entity Framework Core's query visitor, the authorizations can't be
+ // filtered using authorization.Application.Id.Equals(key). To work around this issue,
+ // this method is overriden to use an explicit join before applying the equality check.
+ // See https://github.com/openiddict/openiddict-core/issues/499 for more information.
- ///
- /// Exposes a compiled query allowing to retrieve an authorization using its unique identifier.
- ///
- private static readonly Func> FindById =
- EF.CompileAsyncQuery((TContext context, TKey identifier) =>
- (from authorization in context.Set()
- .Include(authorization => authorization.Application)
- .AsTracking()
- where authorization.Id.Equals(identifier)
- select authorization).FirstOrDefault());
+ var key = ConvertIdentifierFromString(identifier);
+
+ return (from authorization in Authorizations.Include(authorization => authorization.Application).AsTracking()
+ join application in Applications.AsTracking() on authorization.Application.Id equals application.Id
+ where application.Id.Equals(identifier)
+ select authorization).AsAsyncEnumerable();
+ }
///
/// Retrieves an authorization using its unique identifier.
@@ -501,34 +419,19 @@ namespace OpenIddict.EntityFrameworkCore
/// The unique identifier associated with the authorization.
/// The that can be used to abort the operation.
/// The authorization corresponding to the identifier.
- public virtual ValueTask FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken)
+ public virtual async ValueTask FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(identifier))
{
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier));
}
- return new ValueTask(FindById(Context, ConvertIdentifierFromString(identifier)));
- }
+ var key = ConvertIdentifierFromString(identifier);
- ///
- /// Exposes a compiled query allowing to retrieve all the
- /// authorizations corresponding to the specified subject.
- ///
- private static readonly
-#if SUPPORTS_BCL_ASYNC_ENUMERABLE
- Func>
-#else
- Func>
-#endif
- FindBySubject =
-
- EF.CompileAsyncQuery((TContext context, string subject) =>
- from authorization in context.Set()
- .Include(authorization => authorization.Application)
- .AsTracking()
- where authorization.Subject == subject
- select authorization);
+ return await (from authorization in Authorizations.Include(authorization => authorization.Application).AsTracking()
+ where authorization.Id.Equals(key)
+ select authorization).FirstOrDefaultAsync(cancellationToken);
+ }
///
/// Retrieves the subject associated with an authorization.
@@ -544,11 +447,9 @@ namespace OpenIddict.EntityFrameworkCore
throw new ArgumentException("The subject cannot be null or empty.", nameof(subject));
}
- return FindBySubject(Context, subject)
-#if !SUPPORTS_BCL_ASYNC_ENUMERABLE
- .AsAsyncEnumerable(cancellationToken)
-#endif
- ;
+ return (from authorization in Authorizations.Include(authorization => authorization.Application).AsTracking()
+ where authorization.Subject == subject
+ select authorization).AsAsyncEnumerable();
}
///
diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictScopeStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictScopeStore.cs
index 5a56c621..27991a20 100644
--- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictScopeStore.cs
+++ b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictScopeStore.cs
@@ -14,7 +14,6 @@ using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Query;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
@@ -177,15 +176,6 @@ namespace OpenIddict.EntityFrameworkCore
}
}
- ///
- /// Exposes a compiled query allowing to retrieve a scope using its unique identifier.
- ///
- private static readonly Func> FindById =
- EF.CompileAsyncQuery((TContext context, TKey identifier) =>
- (from scope in context.Set().AsTracking()
- where scope.Id.Equals(identifier)
- select scope).FirstOrDefault());
-
///
/// Retrieves a scope using its unique identifier.
///
@@ -195,24 +185,19 @@ namespace OpenIddict.EntityFrameworkCore
/// A that can be used to monitor the asynchronous operation,
/// whose result returns the scope corresponding to the identifier.
///
- public virtual ValueTask FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken)
+ public virtual async ValueTask FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(identifier))
{
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier));
}
- return new ValueTask(FindById(Context, ConvertIdentifierFromString(identifier)));
- }
+ var key = ConvertIdentifierFromString(identifier);
- ///
- /// Exposes a compiled query allowing to retrieve a scope using its name.
- ///
- private static readonly Func> FindByName =
- EF.CompileAsyncQuery((TContext context, string name) =>
- (from scope in context.Set().AsTracking()
- where scope.Name == name
- select scope).FirstOrDefault());
+ return await (from scope in Scopes.AsTracking()
+ where scope.Id.Equals(key)
+ select scope).FirstOrDefaultAsync(cancellationToken);
+ }
///
/// Retrieves a scope using its name.
@@ -223,30 +208,18 @@ namespace OpenIddict.EntityFrameworkCore
/// A that can be used to monitor the asynchronous operation,
/// whose result returns the scope corresponding to the specified name.
///
- public virtual ValueTask FindByNameAsync([NotNull] string name, CancellationToken cancellationToken)
+ public virtual async ValueTask FindByNameAsync([NotNull] string name, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentException("The scope name cannot be null or empty.", nameof(name));
}
- return new ValueTask(FindByName(Context, name));
+ return await (from scope in Scopes.AsTracking()
+ where scope.Name == name
+ select scope).FirstOrDefaultAsync(cancellationToken);
}
- ///
- /// Exposes a compiled query allowing to retrieve a list of scopes using their name.
- ///
- private static readonly
-#if SUPPORTS_BCL_ASYNC_ENUMERABLE
- Func, IAsyncEnumerable>
-#else
- Func, AsyncEnumerable>
-#endif
- FindByNames = EF.CompileAsyncQuery((TContext context, ImmutableArray names) =>
- from scope in context.Set().AsTracking()
- where names.Contains(scope.Name)
- select scope);
-
///
/// Retrieves a list of scopes using their name.
///
@@ -261,34 +234,11 @@ namespace OpenIddict.EntityFrameworkCore
throw new ArgumentException("Scope names cannot be null or empty.", nameof(names));
}
- return FindByNames(Context, names)
-#if !SUPPORTS_BCL_ASYNC_ENUMERABLE
- .AsAsyncEnumerable(cancellationToken)
-#endif
- ;
+ return (from scope in Scopes.AsTracking()
+ where names.Contains(scope.Name)
+ select scope).AsAsyncEnumerable();
}
- ///
- /// Exposes a compiled query allowing to retrieve all the scopes that contain the specified resource.
- ///
- private static readonly
-#if SUPPORTS_BCL_ASYNC_ENUMERABLE
- Func>
-#else
- Func>
-#endif
- FindByResource =
-
- // To optimize the efficiency of the query a bit, only scopes whose stringified
- // Resources column contains the specified resource are returned. Once the scopes
- // are retrieved, a second pass is made to ensure only valid elements are returned.
- // Implementers that use this query in a hot path may want to override this method
- // to use SQL Server 2016 functions like JSON_VALUE to make the query more efficient.
- EF.CompileAsyncQuery((TContext context, string resource) =>
- from scope in context.Set().AsTracking()
- where scope.Resources.Contains(resource)
- select scope);
-
///
/// Retrieves all the scopes that contain the specified resource.
///
@@ -303,11 +253,12 @@ namespace OpenIddict.EntityFrameworkCore
throw new ArgumentException("The resource cannot be null or empty.", nameof(resource));
}
- return FindByResource(Context, resource)
-#if !SUPPORTS_BCL_ASYNC_ENUMERABLE
- .AsAsyncEnumerable(cancellationToken)
-#endif
- .WhereAwait(async scope => (await GetResourcesAsync(scope, cancellationToken)).Contains(resource, StringComparer.Ordinal));
+ var scopes = (from scope in Scopes.AsTracking()
+ where scope.Resources.Contains(resource)
+ select scope).AsAsyncEnumerable();
+
+ return scopes.WhereAwait(async scope =>
+ (await GetResourcesAsync(scope, cancellationToken)).Contains(resource, StringComparer.Ordinal));
}
///
diff --git a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs
index f8e902ad..1611565b 100644
--- a/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs
+++ b/src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs
@@ -15,7 +15,6 @@ using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
@@ -197,32 +196,6 @@ namespace OpenIddict.EntityFrameworkCore
}
}
- ///
- /// Exposes a compiled query allowing to retrieve the tokens corresponding
- /// to the specified subject and associated with the application identifier.
- ///
- private static readonly
-#if SUPPORTS_BCL_ASYNC_ENUMERABLE
- Func>
-#else
- Func>
-#endif
- FindBySubjectAndClient =
-
- // Note: due to a bug in Entity Framework Core's query visitor, the authorizations can't be
- // filtered using token.Application.Id.Equals(key). To work around this issue,
- // this compiled query uses an explicit join before applying the equality check.
- // See https://github.com/openiddict/openiddict-core/issues/499 for more information.
- EF.CompileAsyncQuery((TContext context, TKey identifier, string subject) =>
- from token in context.Set()
- .Include(token => token.Application)
- .Include(token => token.Authorization)
- .AsTracking()
- where token.Subject == subject
- join application in context.Set().AsTracking() on token.Application.Id equals application.Id
- where application.Id.Equals(identifier)
- select token);
-
///
/// Retrieves the tokens corresponding to the specified
/// subject and associated with the application identifier.
@@ -244,37 +217,19 @@ namespace OpenIddict.EntityFrameworkCore
throw new ArgumentException("The client cannot be null or empty.", nameof(client));
}
- return FindBySubjectAndClient(Context, ConvertIdentifierFromString(client), subject)
-#if !SUPPORTS_BCL_ASYNC_ENUMERABLE
- .AsAsyncEnumerable(cancellationToken)
-#endif
- ;
- }
-
- ///
- /// Exposes a compiled query allowing to retrieve the tokens matching the specified parameters.
- ///
- private static readonly
-#if SUPPORTS_BCL_ASYNC_ENUMERABLE
- Func>
-#else
- Func>
-#endif
- FindBySubjectClientAndStatus =
-
// Note: due to a bug in Entity Framework Core's query visitor, the authorizations can't be
// filtered using token.Application.Id.Equals(key). To work around this issue,
// this compiled query uses an explicit join before applying the equality check.
// See https://github.com/openiddict/openiddict-core/issues/499 for more information.
- EF.CompileAsyncQuery((TContext context, TKey identifier, string subject, string status) =>
- from token in context.Set()
- .Include(token => token.Application)
- .Include(token => token.Authorization)
- .AsTracking()
- where token.Subject == subject && token.Status == status
- join application in context.Set().AsTracking() on token.Application.Id equals application.Id
- where application.Id.Equals(identifier)
- select token);
+
+ var key = ConvertIdentifierFromString(client);
+
+ return (from token in Tokens.Include(token => token.Application).Include(token => token.Authorization).AsTracking()
+ where token.Subject == subject
+ join application in Applications.AsTracking() on token.Application.Id equals application.Id
+ where application.Id.Equals(key)
+ select token).AsAsyncEnumerable();
+ }
///
/// Retrieves the tokens matching the specified parameters.
@@ -303,39 +258,20 @@ namespace OpenIddict.EntityFrameworkCore
throw new ArgumentException("The status cannot be null or empty.", nameof(status));
}
- return FindBySubjectClientAndStatus(Context, ConvertIdentifierFromString(client), subject, status)
-#if !SUPPORTS_BCL_ASYNC_ENUMERABLE
- .AsAsyncEnumerable(cancellationToken)
-#endif
- ;
- }
-
- ///
- /// Exposes a compiled query allowing to retrieve the tokens matching the specified parameters.
- ///
- private static readonly
-#if SUPPORTS_BCL_ASYNC_ENUMERABLE
- Func>
-#else
- Func>
-#endif
- FindBySubjectClientStatusAndType =
-
// Note: due to a bug in Entity Framework Core's query visitor, the authorizations can't be
// filtered using token.Application.Id.Equals(key). To work around this issue,
// this compiled query uses an explicit join before applying the equality check.
// See https://github.com/openiddict/openiddict-core/issues/499 for more information.
- EF.CompileAsyncQuery((TContext context, TKey identifier, string subject, string status, string type) =>
- from token in context.Set()
- .Include(token => token.Application)
- .Include(token => token.Authorization)
- .AsTracking()
- where token.Subject == subject &&
- token.Status == status &&
- token.Type == type
- join application in context.Set().AsTracking() on token.Application.Id equals application.Id
- where application.Id.Equals(identifier)
- select token);
+
+ var key = ConvertIdentifierFromString(client);
+
+ return (from token in Tokens.Include(token => token.Application).Include(token => token.Authorization).AsTracking()
+ where token.Subject == subject &&
+ token.Status == status
+ join application in Applications.AsTracking() on token.Application.Id equals application.Id
+ where application.Id.Equals(key)
+ select token).AsAsyncEnumerable();
+ }
///
/// Retrieves the tokens matching the specified parameters.
@@ -370,37 +306,21 @@ namespace OpenIddict.EntityFrameworkCore
throw new ArgumentException("The type cannot be null or empty.", nameof(type));
}
- return FindBySubjectClientStatusAndType(Context, ConvertIdentifierFromString(client), subject, status, type)
-#if !SUPPORTS_BCL_ASYNC_ENUMERABLE
- .AsAsyncEnumerable(cancellationToken)
-#endif
- ;
- }
-
- ///
- /// Exposes a compiled query allowing to retrieve the list of
- /// tokens corresponding to the specified application identifier.
- ///
- private static readonly
-#if SUPPORTS_BCL_ASYNC_ENUMERABLE
- Func>
-#else
- Func>
-#endif
- FindByApplicationId =
-
- // Note: due to a bug in Entity Framework Core's query visitor, the tokens can't be
+ // Note: due to a bug in Entity Framework Core's query visitor, the authorizations can't be
// filtered using token.Application.Id.Equals(key). To work around this issue,
// this compiled query uses an explicit join before applying the equality check.
// See https://github.com/openiddict/openiddict-core/issues/499 for more information.
- EF.CompileAsyncQuery((TContext context, TKey identifier) =>
- from token in context.Set()
- .Include(token => token.Application)
- .Include(token => token.Authorization)
- .AsTracking()
- join application in context.Set().AsTracking() on token.Application.Id equals application.Id
- where application.Id.Equals(identifier)
- select token);
+
+ var key = ConvertIdentifierFromString(client);
+
+ return (from token in Tokens.Include(token => token.Application).Include(token => token.Authorization).AsTracking()
+ where token.Subject == subject &&
+ token.Status == status &&
+ token.Type == type
+ join application in Applications.AsTracking() on token.Application.Id equals application.Id
+ where application.Id.Equals(key)
+ select token).AsAsyncEnumerable();
+ }
///
/// Retrieves the list of tokens corresponding to the specified application identifier.
@@ -415,37 +335,18 @@ namespace OpenIddict.EntityFrameworkCore
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier));
}
- return FindByApplicationId(Context, ConvertIdentifierFromString(identifier))
-#if !SUPPORTS_BCL_ASYNC_ENUMERABLE
- .AsAsyncEnumerable(cancellationToken)
-#endif
- ;
- }
-
- ///
- /// Exposes a compiled query allowing to retrieve the list of
- /// tokens corresponding to the specified authorization identifier.
- ///
- private static readonly
-#if SUPPORTS_BCL_ASYNC_ENUMERABLE
- Func>
-#else
- Func>
-#endif
- FindByAuthorizationId =
-
// Note: due to a bug in Entity Framework Core's query visitor, the tokens can't be
- // filtered using token.Authorization.Id.Equals(key). To work around this issue,
- // this compiled query uses an explicit join before applying the equality check.
+ // filtered using token.Application.Id.Equals(key). To work around this issue,
+ // this method is overriden to use an explicit join before applying the equality check.
// See https://github.com/openiddict/openiddict-core/issues/499 for more information.
- EF.CompileAsyncQuery((TContext context, TKey identifier) =>
- from token in context.Set()
- .Include(token => token.Application)
- .Include(token => token.Authorization)
- .AsTracking()
- join authorization in context.Set().AsTracking() on token.Authorization.Id equals authorization.Id
- where authorization.Id.Equals(identifier)
- select token);
+
+ var key = ConvertIdentifierFromString(identifier);
+
+ return (from token in Tokens.Include(token => token.Application).Include(token => token.Authorization).AsTracking()
+ join application in Applications.AsTracking() on token.Application.Id equals application.Id
+ where application.Id.Equals(key)
+ select token).AsAsyncEnumerable();
+ }
///
/// Retrieves the list of tokens corresponding to the specified authorization identifier.
@@ -460,24 +361,18 @@ namespace OpenIddict.EntityFrameworkCore
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier));
}
- return FindByAuthorizationId(Context, ConvertIdentifierFromString(identifier))
-#if !SUPPORTS_BCL_ASYNC_ENUMERABLE
- .AsAsyncEnumerable(cancellationToken)
-#endif
- ;
- }
+ // Note: due to a bug in Entity Framework Core's query visitor, the tokens can't be
+ // filtered using token.Authorization.Id.Equals(key). To work around this issue,
+ // this method is overriden to use an explicit join before applying the equality check.
+ // See https://github.com/openiddict/openiddict-core/issues/499 for more information.
- ///
- /// Exposes a compiled query allowing to retrieve a token using its unique identifier.
- ///
- private static readonly Func> FindById =
- EF.CompileAsyncQuery((TContext context, TKey identifier) =>
- (from token in context.Set()
- .Include(token => token.Application)
- .Include(token => token.Authorization)
- .AsTracking()
- where token.Id.Equals(identifier)
- select token).FirstOrDefault());
+ var key = ConvertIdentifierFromString(identifier);
+
+ return (from token in Tokens.Include(token => token.Application).Include(token => token.Authorization).AsTracking()
+ join authorization in Authorizations.AsTracking() on token.Authorization.Id equals authorization.Id
+ where authorization.Id.Equals(key)
+ select token).AsAsyncEnumerable();
+ }
///
/// Retrieves a token using its unique identifier.
@@ -488,28 +383,19 @@ namespace OpenIddict.EntityFrameworkCore
/// A that can be used to monitor the asynchronous operation,
/// whose result returns the token corresponding to the unique identifier.
///
- public virtual ValueTask FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken)
+ public virtual async ValueTask FindByIdAsync([NotNull] string identifier, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(identifier))
{
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier));
}
- return new ValueTask(FindById(Context, ConvertIdentifierFromString(identifier)));
- }
+ var key = ConvertIdentifierFromString(identifier);
- ///
- /// Exposes a compiled query allowing to retrieve the list of
- /// tokens corresponding to the specified reference identifier.
- ///
- private static readonly Func> FindByReferenceId =
- EF.CompileAsyncQuery((TContext context, string identifier) =>
- (from token in context.Set()
- .Include(token => token.Application)
- .Include(token => token.Authorization)
- .AsTracking()
- where token.ReferenceId == identifier
- select token).FirstOrDefault());
+ return await (from token in Tokens.Include(token => token.Application).Include(token => token.Authorization).AsTracking()
+ where token.Id.Equals(key)
+ select token).FirstOrDefaultAsync(cancellationToken);
+ }
///
/// Retrieves the list of tokens corresponding to the specified reference identifier.
@@ -521,34 +407,18 @@ namespace OpenIddict.EntityFrameworkCore
/// A that can be used to monitor the asynchronous operation,
/// whose result returns the tokens corresponding to the specified reference identifier.
///
- public virtual ValueTask FindByReferenceIdAsync([NotNull] string identifier, CancellationToken cancellationToken)
+ public virtual async ValueTask FindByReferenceIdAsync([NotNull] string identifier, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(identifier))
{
throw new ArgumentException("The identifier cannot be null or empty.", nameof(identifier));
}
- return new ValueTask(FindByReferenceId(Context, identifier));
+ return await (from token in Tokens.Include(token => token.Application).Include(token => token.Authorization).AsTracking()
+ where token.ReferenceId == identifier
+ select token).FirstOrDefaultAsync(cancellationToken);
}
- ///
- /// Exposes a compiled query allowing to retrieve the
- /// list of tokens corresponding to the specified subject.
- ///
- private static readonly
-#if SUPPORTS_BCL_ASYNC_ENUMERABLE
- Func>
-#else
- Func>
-#endif
- FindBySubject = EF.CompileAsyncQuery((TContext context, string subject) =>
- from token in context.Set()
- .Include(token => token.Application)
- .Include(token => token.Authorization)
- .AsTracking()
- where token.Subject == subject
- select token);
-
///
/// Retrieves the list of tokens corresponding to the specified subject.
///
@@ -562,11 +432,9 @@ namespace OpenIddict.EntityFrameworkCore
throw new ArgumentException("The subject cannot be null or empty.", nameof(subject));
}
- return FindBySubject(Context, subject)
-#if !SUPPORTS_BCL_ASYNC_ENUMERABLE
- .AsAsyncEnumerable(cancellationToken)
-#endif
- ;
+ return (from token in Tokens.Include(token => token.Application).Include(token => token.Authorization).AsTracking()
+ where token.Subject == subject
+ select token).AsAsyncEnumerable();
}
///