Browse Source

Update the Entity Framework Core stores to be compatible with QueryTrackingBehavior.NoTracking

pull/575/head
Kévin Chalet 9 years ago
parent
commit
866c61f399
  1. 23
      src/OpenIddict.Core/Stores/OpenIddictAuthorizationStore.cs
  2. 42
      src/OpenIddict.Core/Stores/OpenIddictTokenStore.cs
  3. 1
      src/OpenIddict.EntityFramework/Stores/OpenIddictApplicationStore.cs
  4. 5
      src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.cs
  5. 6
      src/OpenIddict.EntityFramework/Stores/OpenIddictTokenStore.cs
  6. 13
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictApplicationStore.cs
  7. 33
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs
  8. 4
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictScopeStore.cs
  9. 22
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs

23
src/OpenIddict.Core/Stores/OpenIddictAuthorizationStore.cs

@ -281,7 +281,7 @@ namespace OpenIddict.Core
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation, /// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the application identifier associated with the authorization. /// whose result returns the application identifier associated with the authorization.
/// </returns> /// </returns>
public virtual async ValueTask<string> GetApplicationIdAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken) public virtual ValueTask<string> GetApplicationIdAsync([NotNull] TAuthorization authorization, CancellationToken cancellationToken)
{ {
if (authorization == null) if (authorization == null)
{ {
@ -290,17 +290,22 @@ namespace OpenIddict.Core
if (authorization.Application != null) if (authorization.Application != null)
{ {
return ConvertIdentifierToString(authorization.Application.Id); return new ValueTask<string>(ConvertIdentifierToString(authorization.Application.Id));
} }
IQueryable<TKey> Query(IQueryable<TAuthorization> authorizations, TKey key) async Task<string> RetrieveApplicationIdAsync()
=> from element in authorizations {
where element.Id.Equals(key) && IQueryable<TKey> Query(IQueryable<TAuthorization> authorizations, TKey key)
element.Application != null => from element in authorizations
select element.Application.Id; where element.Id.Equals(key) &&
element.Application != null
select element.Application.Id;
return ConvertIdentifierToString(await GetAsync(
(authorizations, key) => Query(authorizations, key), authorization.Id, cancellationToken));
}
return ConvertIdentifierToString(await GetAsync( return new ValueTask<string>(RetrieveApplicationIdAsync());
(authorizations, key) => Query(authorizations, key), authorization.Id, cancellationToken));
} }
/// <summary> /// <summary>

42
src/OpenIddict.Core/Stores/OpenIddictTokenStore.cs

@ -239,7 +239,7 @@ namespace OpenIddict.Core
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation, /// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the application identifier associated with the token. /// whose result returns the application identifier associated with the token.
/// </returns> /// </returns>
public virtual async ValueTask<string> GetApplicationIdAsync([NotNull] TToken token, CancellationToken cancellationToken) public virtual ValueTask<string> GetApplicationIdAsync([NotNull] TToken token, CancellationToken cancellationToken)
{ {
if (token == null) if (token == null)
{ {
@ -248,16 +248,21 @@ namespace OpenIddict.Core
if (token.Application != null) if (token.Application != null)
{ {
return ConvertIdentifierToString(token.Application.Id); return new ValueTask<string>(ConvertIdentifierToString(token.Application.Id));
} }
IQueryable<TKey> Query(IQueryable<TToken> tokens, TKey key) async Task<string> RetrieveApplicationIdAsync()
=> from element in tokens {
where element.Id.Equals(key) && IQueryable<TKey> Query(IQueryable<TToken> tokens, TKey key)
element.Application != null => from element in tokens
select element.Application.Id; where element.Id.Equals(key) &&
element.Application != null
select element.Application.Id;
return ConvertIdentifierToString(await GetAsync((tokens, key) => Query(tokens, key), token.Id, cancellationToken));
}
return ConvertIdentifierToString(await GetAsync((tokens, key) => Query(tokens, key), token.Id, cancellationToken)); return new ValueTask<string>(RetrieveApplicationIdAsync());
} }
/// <summary> /// <summary>
@ -269,7 +274,7 @@ namespace OpenIddict.Core
/// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation, /// A <see cref="ValueTask{TResult}"/> that can be used to monitor the asynchronous operation,
/// whose result returns the authorization identifier associated with the token. /// whose result returns the authorization identifier associated with the token.
/// </returns> /// </returns>
public virtual async ValueTask<string> GetAuthorizationIdAsync([NotNull] TToken token, CancellationToken cancellationToken) public virtual ValueTask<string> GetAuthorizationIdAsync([NotNull] TToken token, CancellationToken cancellationToken)
{ {
if (token == null) if (token == null)
{ {
@ -278,16 +283,21 @@ namespace OpenIddict.Core
if (token.Authorization != null) if (token.Authorization != null)
{ {
return ConvertIdentifierToString(token.Authorization.Id); return new ValueTask<string>(ConvertIdentifierToString(token.Authorization.Id));
} }
IQueryable<TKey> Query(IQueryable<TToken> tokens, TKey key) async Task<string> RetrieveAuthorizationIdAsync()
=> from element in tokens {
where element.Id.Equals(key) && IQueryable<TKey> Query(IQueryable<TToken> tokens, TKey key)
element.Authorization != null => from element in tokens
select element.Authorization.Id; where element.Id.Equals(key) &&
element.Authorization != null
select element.Authorization.Id;
return ConvertIdentifierToString(await GetAsync((tokens, key) => Query(tokens, key), token.Id, cancellationToken));
}
return ConvertIdentifierToString(await GetAsync((tokens, key) => Query(tokens, key), token.Id, cancellationToken)); return new ValueTask<string>(RetrieveAuthorizationIdAsync());
} }
/// <summary> /// <summary>

1
src/OpenIddict.EntityFramework/Stores/OpenIddictApplicationStore.cs

@ -168,6 +168,7 @@ namespace OpenIddict.EntityFramework
Task<List<TToken>> ListTokensAsync() Task<List<TToken>> ListTokensAsync()
=> (from token in Tokens => (from token in Tokens
where token.Authorization == null
where token.Application.Id.Equals(application.Id) where token.Application.Id.Equals(application.Id)
select token).ToListAsync(cancellationToken); select token).ToListAsync(cancellationToken);

5
src/OpenIddict.EntityFramework/Stores/OpenIddictAuthorizationStore.cs

@ -167,7 +167,7 @@ namespace OpenIddict.EntityFramework
where token.Authorization.Id.Equals(authorization.Id) where token.Authorization.Id.Equals(authorization.Id)
select token).ToListAsync(cancellationToken); select token).ToListAsync(cancellationToken);
// Remove all the tokens associated with the application. // Remove all the tokens associated with the authorization.
foreach (var token in await ListTokensAsync()) foreach (var token in await ListTokensAsync())
{ {
Tokens.Remove(token); Tokens.Remove(token);
@ -383,7 +383,8 @@ namespace OpenIddict.EntityFramework
/// <returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation. /// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns> /// </returns>
public override async Task SetApplicationIdAsync([NotNull] TAuthorization authorization, [CanBeNull] string identifier, CancellationToken cancellationToken) public override async Task SetApplicationIdAsync([NotNull] TAuthorization authorization,
[CanBeNull] string identifier, CancellationToken cancellationToken)
{ {
if (authorization == null) if (authorization == null)
{ {

6
src/OpenIddict.EntityFramework/Stores/OpenIddictTokenStore.cs

@ -407,7 +407,8 @@ namespace OpenIddict.EntityFramework
/// <returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation. /// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns> /// </returns>
public override async Task SetApplicationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken) public override async Task SetApplicationIdAsync([NotNull] TToken token,
[CanBeNull] string identifier, CancellationToken cancellationToken)
{ {
if (token == null) if (token == null)
{ {
@ -452,7 +453,8 @@ namespace OpenIddict.EntityFramework
/// <returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation. /// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns> /// </returns>
public override async Task SetAuthorizationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken) public override async Task SetAuthorizationIdAsync([NotNull] TToken token,
[CanBeNull] string identifier, CancellationToken cancellationToken)
{ {
if (token == null) if (token == null)
{ {

13
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictApplicationStore.cs

@ -167,8 +167,8 @@ namespace OpenIddict.EntityFrameworkCore
// See https://github.com/openiddict/openiddict-core/issues/499 for more information. // See https://github.com/openiddict/openiddict-core/issues/499 for more information.
Task<List<TAuthorization>> ListAuthorizationsAsync() Task<List<TAuthorization>> ListAuthorizationsAsync()
=> (from authorization in Authorizations.Include(authorization => authorization.Tokens) => (from authorization in Authorizations.Include(authorization => authorization.Tokens).AsTracking()
join element in Applications on authorization.Application.Id equals element.Id join element in Applications.AsTracking() on authorization.Application.Id equals element.Id
where element.Id.Equals(application.Id) where element.Id.Equals(application.Id)
select authorization).ToListAsync(cancellationToken); select authorization).ToListAsync(cancellationToken);
@ -178,8 +178,9 @@ namespace OpenIddict.EntityFrameworkCore
// See https://github.com/openiddict/openiddict-core/issues/499 for more information. // See https://github.com/openiddict/openiddict-core/issues/499 for more information.
Task<List<TToken>> ListTokensAsync() Task<List<TToken>> ListTokensAsync()
=> (from token in Tokens => (from token in Tokens.AsTracking()
join element in Applications on token.Application.Id equals element.Id where token.Authorization == null
join element in Applications.AsTracking() on token.Application.Id equals element.Id
where element.Id.Equals(application.Id) where element.Id.Equals(application.Id)
select token).ToListAsync(cancellationToken); select token).ToListAsync(cancellationToken);
@ -246,7 +247,7 @@ namespace OpenIddict.EntityFrameworkCore
throw new ArgumentNullException(nameof(query)); throw new ArgumentNullException(nameof(query));
} }
return query(Applications, state).FirstOrDefaultAsync(cancellationToken); return query(Applications.AsTracking(), state).FirstOrDefaultAsync(cancellationToken);
} }
/// <summary> /// <summary>
@ -270,7 +271,7 @@ namespace OpenIddict.EntityFrameworkCore
throw new ArgumentNullException(nameof(query)); throw new ArgumentNullException(nameof(query));
} }
return ImmutableArray.CreateRange(await query(Applications, state).ToListAsync(cancellationToken)); return ImmutableArray.CreateRange(await query(Applications.AsTracking(), state).ToListAsync(cancellationToken));
} }
/// <summary> /// <summary>

33
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictAuthorizationStore.cs

@ -170,12 +170,12 @@ namespace OpenIddict.EntityFrameworkCore
// See https://github.com/openiddict/openiddict-core/issues/499 for more information. // See https://github.com/openiddict/openiddict-core/issues/499 for more information.
Task<List<TToken>> ListTokensAsync() Task<List<TToken>> ListTokensAsync()
=> (from token in Tokens => (from token in Tokens.AsTracking()
join element in Authorizations on token.Authorization.Id equals element.Id join element in Authorizations.AsTracking() on token.Authorization.Id equals element.Id
where element.Id.Equals(authorization.Id) where element.Id.Equals(authorization.Id)
select token).ToListAsync(cancellationToken); select token).ToListAsync(cancellationToken);
// Remove all the tokens associated with the application. // Remove all the tokens associated with the authorization.
foreach (var token in await ListTokensAsync()) foreach (var token in await ListTokensAsync())
{ {
Context.Remove(token); Context.Remove(token);
@ -217,9 +217,9 @@ namespace OpenIddict.EntityFrameworkCore
IQueryable<TAuthorization> Query(IQueryable<TAuthorization> authorizations, IQueryable<TAuthorization> Query(IQueryable<TAuthorization> authorizations,
IQueryable<TApplication> applications, TKey key, string principal) IQueryable<TApplication> applications, TKey key, string principal)
=> from authorization in authorizations.Include(authorization => authorization.Application) => from authorization in authorizations.Include(authorization => authorization.Application).AsTracking()
where authorization.Subject == principal where authorization.Subject == principal
join application in applications on authorization.Application.Id equals application.Id join application in applications.AsTracking() on authorization.Application.Id equals application.Id
where application.Id.Equals(key) where application.Id.Equals(key)
select authorization; select authorization;
@ -264,10 +264,9 @@ namespace OpenIddict.EntityFrameworkCore
IQueryable<TAuthorization> Query(IQueryable<TAuthorization> authorizations, IQueryable<TAuthorization> Query(IQueryable<TAuthorization> authorizations,
IQueryable<TApplication> applications, TKey key, string principal, string state) IQueryable<TApplication> applications, TKey key, string principal, string state)
=> from authorization in authorizations.Include(authorization => authorization.Application) => from authorization in authorizations.Include(authorization => authorization.Application).AsTracking()
where authorization.Subject == principal && where authorization.Subject == principal && authorization.Status == state
authorization.Status == state join application in applications.AsTracking() on authorization.Application.Id equals application.Id
join application in applications on authorization.Application.Id equals application.Id
where application.Id.Equals(key) where application.Id.Equals(key)
select authorization; select authorization;
@ -318,11 +317,11 @@ namespace OpenIddict.EntityFrameworkCore
IQueryable<TAuthorization> Query(IQueryable<TAuthorization> authorizations, IQueryable<TAuthorization> Query(IQueryable<TAuthorization> authorizations,
IQueryable<TApplication> applications, TKey key, string principal, string state, string kind) IQueryable<TApplication> applications, TKey key, string principal, string state, string kind)
=> from authorization in authorizations.Include(authorization => authorization.Application) => from authorization in authorizations.Include(authorization => authorization.Application).AsTracking()
where authorization.Subject == principal && where authorization.Subject == principal &&
authorization.Status == state && authorization.Status == state &&
authorization.Type == kind authorization.Type == kind
join application in applications on authorization.Application.Id equals application.Id join application in applications.AsTracking() on authorization.Application.Id equals application.Id
where application.Id.Equals(key) where application.Id.Equals(key)
select authorization; select authorization;
@ -416,7 +415,9 @@ namespace OpenIddict.EntityFrameworkCore
throw new ArgumentNullException(nameof(query)); throw new ArgumentNullException(nameof(query));
} }
return query(Authorizations.Include(authorization => authorization.Application), state).FirstOrDefaultAsync(cancellationToken); return query(
Authorizations.Include(authorization => authorization.Application)
.AsTracking(), state).FirstOrDefaultAsync(cancellationToken);
} }
/// <summary> /// <summary>
@ -441,7 +442,8 @@ namespace OpenIddict.EntityFrameworkCore
} }
return ImmutableArray.CreateRange(await query( return ImmutableArray.CreateRange(await query(
Authorizations.Include(authorization => authorization.Application), state).ToListAsync(cancellationToken)); Authorizations.Include(authorization => authorization.Application)
.AsTracking(), state).ToListAsync(cancellationToken));
} }
/// <summary> /// <summary>
@ -460,7 +462,7 @@ namespace OpenIddict.EntityFrameworkCore
IList<Exception> exceptions = null; IList<Exception> exceptions = null;
IQueryable<TAuthorization> Query(IQueryable<TAuthorization> authorizations, int offset) IQueryable<TAuthorization> Query(IQueryable<TAuthorization> authorizations, int offset)
=> (from authorization in authorizations.Include(authorization => authorization.Tokens) => (from authorization in authorizations.Include(authorization => authorization.Tokens).AsTracking()
where authorization.Status != OpenIddictConstants.Statuses.Valid || where authorization.Status != OpenIddictConstants.Statuses.Valid ||
(authorization.Type == OpenIddictConstants.AuthorizationTypes.AdHoc && (authorization.Type == OpenIddictConstants.AuthorizationTypes.AdHoc &&
!authorization.Tokens.Any(token => token.Status == OpenIddictConstants.Statuses.Valid)) !authorization.Tokens.Any(token => token.Status == OpenIddictConstants.Statuses.Valid))
@ -545,7 +547,8 @@ namespace OpenIddict.EntityFrameworkCore
/// <returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation. /// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns> /// </returns>
public override async Task SetApplicationIdAsync([NotNull] TAuthorization authorization, [CanBeNull] string identifier, CancellationToken cancellationToken) public override async Task SetApplicationIdAsync([NotNull] TAuthorization authorization,
[CanBeNull] string identifier, CancellationToken cancellationToken)
{ {
if (authorization == null) if (authorization == null)
{ {

4
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictScopeStore.cs

@ -186,7 +186,7 @@ namespace OpenIddict.EntityFrameworkCore
throw new ArgumentNullException(nameof(query)); throw new ArgumentNullException(nameof(query));
} }
return query(Scopes, state).FirstOrDefaultAsync(cancellationToken); return query(Scopes.AsTracking(), state).FirstOrDefaultAsync(cancellationToken);
} }
/// <summary> /// <summary>
@ -210,7 +210,7 @@ namespace OpenIddict.EntityFrameworkCore
throw new ArgumentNullException(nameof(query)); throw new ArgumentNullException(nameof(query));
} }
return ImmutableArray.CreateRange(await query(Scopes, state).ToListAsync(cancellationToken)); return ImmutableArray.CreateRange(await query(Scopes.AsTracking(), state).ToListAsync(cancellationToken));
} }
/// <summary> /// <summary>

22
src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictTokenStore.cs

@ -189,8 +189,8 @@ namespace OpenIddict.EntityFrameworkCore
// See https://github.com/openiddict/openiddict-core/issues/499 for more information. // See https://github.com/openiddict/openiddict-core/issues/499 for more information.
IQueryable<TToken> Query(IQueryable<TApplication> applications, IQueryable<TToken> tokens, TKey key) IQueryable<TToken> Query(IQueryable<TApplication> applications, IQueryable<TToken> tokens, TKey key)
=> from token in tokens.Include(token => token.Application).Include(token => token.Authorization) => from token in tokens.Include(token => token.Application).Include(token => token.Authorization).AsTracking()
join application in applications on token.Application.Id equals application.Id join application in applications.AsTracking() on token.Application.Id equals application.Id
where application.Id.Equals(key) where application.Id.Equals(key)
select token; select token;
@ -220,8 +220,8 @@ namespace OpenIddict.EntityFrameworkCore
// See https://github.com/openiddict/openiddict-core/issues/499 for more information. // See https://github.com/openiddict/openiddict-core/issues/499 for more information.
IQueryable<TToken> Query(IQueryable<TAuthorization> authorizations, IQueryable<TToken> tokens, TKey key) IQueryable<TToken> Query(IQueryable<TAuthorization> authorizations, IQueryable<TToken> tokens, TKey key)
=> from token in tokens.Include(token => token.Application).Include(token => token.Authorization) => from token in tokens.Include(token => token.Application).Include(token => token.Authorization).AsTracking()
join authorization in authorizations on token.Authorization.Id equals authorization.Id join authorization in authorizations.AsTracking() on token.Authorization.Id equals authorization.Id
where authorization.Id.Equals(key) where authorization.Id.Equals(key)
select token; select token;
@ -317,7 +317,8 @@ namespace OpenIddict.EntityFrameworkCore
return query( return query(
Tokens.Include(token => token.Application) Tokens.Include(token => token.Application)
.Include(token => token.Authorization), state).FirstOrDefaultAsync(cancellationToken); .Include(token => token.Authorization)
.AsTracking(), state).FirstOrDefaultAsync(cancellationToken);
} }
/// <summary> /// <summary>
@ -379,7 +380,8 @@ namespace OpenIddict.EntityFrameworkCore
return ImmutableArray.CreateRange(await query( return ImmutableArray.CreateRange(await query(
Tokens.Include(token => token.Application) Tokens.Include(token => token.Application)
.Include(token => token.Authorization), state).ToListAsync(cancellationToken)); .Include(token => token.Authorization)
.AsTracking(), state).ToListAsync(cancellationToken));
} }
/// <summary> /// <summary>
@ -398,7 +400,7 @@ namespace OpenIddict.EntityFrameworkCore
IList<Exception> exceptions = null; IList<Exception> exceptions = null;
IQueryable<TToken> Query(IQueryable<TToken> tokens, int offset) IQueryable<TToken> Query(IQueryable<TToken> tokens, int offset)
=> (from token in tokens => (from token in tokens.AsTracking()
where token.ExpirationDate < DateTimeOffset.UtcNow || where token.ExpirationDate < DateTimeOffset.UtcNow ||
token.Status != OpenIddictConstants.Statuses.Valid token.Status != OpenIddictConstants.Statuses.Valid
orderby token.Id orderby token.Id
@ -481,7 +483,8 @@ namespace OpenIddict.EntityFrameworkCore
/// <returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation. /// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns> /// </returns>
public override async Task SetApplicationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken) public override async Task SetApplicationIdAsync([NotNull] TToken token,
[CanBeNull] string identifier, CancellationToken cancellationToken)
{ {
if (token == null) if (token == null)
{ {
@ -526,7 +529,8 @@ namespace OpenIddict.EntityFrameworkCore
/// <returns> /// <returns>
/// A <see cref="Task"/> that can be used to monitor the asynchronous operation. /// A <see cref="Task"/> that can be used to monitor the asynchronous operation.
/// </returns> /// </returns>
public override async Task SetAuthorizationIdAsync([NotNull] TToken token, [CanBeNull] string identifier, CancellationToken cancellationToken) public override async Task SetAuthorizationIdAsync([NotNull] TToken token,
[CanBeNull] string identifier, CancellationToken cancellationToken)
{ {
if (token == null) if (token == null)
{ {

Loading…
Cancel
Save