Browse Source

Update the EF Core stores to resolve the navigation properties via the change tracker when possible

pull/1972/head
Kévin Chalet 2 years ago
parent
commit
9ee5fe53ab
  1. 1
      Directory.Build.targets
  2. 23
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreAuthorizationStore.cs
  3. 46
      src/OpenIddict.EntityFrameworkCore/Stores/OpenIddictEntityFrameworkCoreTokenStore.cs

1
Directory.Build.targets

@ -80,6 +80,7 @@
Condition=" ('$(TargetFrameworkIdentifier)' == '.NETCoreApp' And $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '3.0'))) Or Condition=" ('$(TargetFrameworkIdentifier)' == '.NETCoreApp' And $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '3.0'))) Or
('$(TargetFrameworkIdentifier)' == '.NETStandard' And $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '2.1'))) "> ('$(TargetFrameworkIdentifier)' == '.NETStandard' And $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '2.1'))) ">
<DefineConstants>$(DefineConstants);SUPPORTS_BCL_ASYNC_ENUMERABLE</DefineConstants> <DefineConstants>$(DefineConstants);SUPPORTS_BCL_ASYNC_ENUMERABLE</DefineConstants>
<DefineConstants>$(DefineConstants);SUPPORTS_DBSET_VALUETASK_FINDASYNC</DefineConstants>
</PropertyGroup> </PropertyGroup>
<PropertyGroup <PropertyGroup

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

@ -802,14 +802,27 @@ public class OpenIddictEntityFrameworkCoreAuthorizationStore<TAuthorization, TAp
if (!string.IsNullOrEmpty(identifier)) if (!string.IsNullOrEmpty(identifier))
{ {
#if SUPPORTS_DBSET_VALUETASK_FINDASYNC
authorization.Application = await Applications.FindAsync([ConvertIdentifierFromString(identifier)], cancellationToken);
#else
// Warning: when targeting older TFMs, FindAsync() is deliberately not used to work around a breaking
// change introduced in Entity Framework Core 3.x (where a ValueTask instead of a Task is now returned).
var key = ConvertIdentifierFromString(identifier); var key = ConvertIdentifierFromString(identifier);
// Warning: FindAsync() is deliberately not used to work around a breaking change introduced authorization.Application = GetTrackedEntity() ?? await QueryAsync() ??
// in Entity Framework Core 3.x (where a ValueTask instead of a Task is now returned).
authorization.Application = await Applications.AsQueryable()
.AsTracking()
.FirstOrDefaultAsync(application => application.Id!.Equals(key), cancellationToken) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0244)); throw new InvalidOperationException(SR.GetResourceString(SR.ID0244));
TApplication? GetTrackedEntity() =>
(from entry in Context.ChangeTracker.Entries<TApplication>()
where entry.Entity.Id is TKey identifier && identifier.Equals(key)
select entry.Entity).FirstOrDefault();
Task<TApplication?> QueryAsync() =>
(from application in Applications.AsTracking()
where application.Id!.Equals(key)
select application).FirstOrDefaultAsync(cancellationToken);
#endif
} }
else else

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

@ -802,14 +802,27 @@ public class OpenIddictEntityFrameworkCoreTokenStore<TToken, TApplication, TAuth
if (!string.IsNullOrEmpty(identifier)) if (!string.IsNullOrEmpty(identifier))
{ {
#if SUPPORTS_DBSET_VALUETASK_FINDASYNC
token.Application = await Applications.FindAsync([ConvertIdentifierFromString(identifier)], cancellationToken);
#else
// Warning: when targeting older TFMs, FindAsync() is deliberately not used to work around a breaking
// change introduced in Entity Framework Core 3.x (where a ValueTask instead of a Task is now returned).
var key = ConvertIdentifierFromString(identifier); var key = ConvertIdentifierFromString(identifier);
// Warning: FindAsync() is deliberately not used to work around a breaking change introduced token.Application = GetTrackedEntity() ?? await QueryAsync() ??
// in Entity Framework Core 3.x (where a ValueTask instead of a Task is now returned).
token.Application = await Applications.AsQueryable()
.AsTracking()
.FirstOrDefaultAsync(application => application.Id!.Equals(key), cancellationToken) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0250)); throw new InvalidOperationException(SR.GetResourceString(SR.ID0250));
TApplication? GetTrackedEntity() =>
(from entry in Context.ChangeTracker.Entries<TApplication>()
where entry.Entity.Id is TKey identifier && identifier.Equals(key)
select entry.Entity).FirstOrDefault();
Task<TApplication?> QueryAsync() =>
(from application in Applications.AsTracking()
where application.Id!.Equals(key)
select application).FirstOrDefaultAsync(cancellationToken);
#endif
} }
else else
@ -840,14 +853,27 @@ public class OpenIddictEntityFrameworkCoreTokenStore<TToken, TApplication, TAuth
if (!string.IsNullOrEmpty(identifier)) if (!string.IsNullOrEmpty(identifier))
{ {
#if SUPPORTS_DBSET_VALUETASK_FINDASYNC
token.Authorization = await Authorizations.FindAsync([ConvertIdentifierFromString(identifier)], cancellationToken);
#else
// Warning: when targeting older TFMs, FindAsync() is deliberately not used to work around a breaking
// change introduced in Entity Framework Core 3.x (where a ValueTask instead of a Task is now returned).
var key = ConvertIdentifierFromString(identifier); var key = ConvertIdentifierFromString(identifier);
// Warning: FindAsync() is deliberately not used to work around a breaking change introduced token.Authorization = GetTrackedEntity() ?? await QueryAsync() ??
// in Entity Framework Core 3.x (where a ValueTask instead of a Task is now returned).
token.Authorization = await Authorizations.AsQueryable()
.AsTracking()
.FirstOrDefaultAsync(authorization => authorization.Id!.Equals(key), cancellationToken) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0251)); throw new InvalidOperationException(SR.GetResourceString(SR.ID0251));
TAuthorization? GetTrackedEntity() =>
(from entry in Context.ChangeTracker.Entries<TAuthorization>()
where entry.Entity.Id is TKey identifier && identifier.Equals(key)
select entry.Entity).FirstOrDefault();
Task<TAuthorization?> QueryAsync() =>
(from authorization in Authorizations.AsTracking()
where authorization.Id!.Equals(key)
select authorization).FirstOrDefaultAsync(cancellationToken);
#endif
} }
else else

Loading…
Cancel
Save