Browse Source

Replace the local CreateTransaction() functions in the EF 6 stores by an internal CreateTransaction() helper

pull/2011/head
Kévin Chalet 2 years ago
parent
commit
60cc487298
  1. 25
      src/OpenIddict.EntityFramework/OpenIddictEntityFrameworkHelpers.cs
  2. 16
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkApplicationStore.cs
  3. 33
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkAuthorizationStore.cs
  4. 18
      src/OpenIddict.EntityFramework/Stores/OpenIddictEntityFrameworkTokenStore.cs

25
src/OpenIddict.EntityFramework/OpenIddictEntityFrameworkHelpers.cs

@ -9,6 +9,7 @@ using System.Runtime.CompilerServices;
using Microsoft.Extensions.DependencyInjection;
using OpenIddict.EntityFramework;
using OpenIddict.EntityFramework.Models;
using OpenIddict.Extensions;
namespace System.Data.Entity;
@ -86,4 +87,28 @@ public static class OpenIddictEntityFrameworkHelpers
}
}
}
/// <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)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
try
{
return context.Database.BeginTransaction(level);
}
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
return null;
}
}
}

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

@ -18,7 +18,6 @@ using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using OpenIddict.EntityFramework.Models;
using OpenIddict.Extensions;
using static OpenIddict.Abstractions.OpenIddictExceptions;
namespace OpenIddict.EntityFramework;
@ -133,19 +132,6 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
throw new ArgumentNullException(nameof(application));
}
DbContextTransaction? CreateTransaction()
{
try
{
return Context.Database.BeginTransaction(IsolationLevel.Serializable);
}
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
return null;
}
}
Task<List<TAuthorization>> ListAuthorizationsAsync()
=> (from authorization in Authorizations.Include(authorization => authorization.Tokens)
where authorization.Application!.Id!.Equals(application.Id)
@ -160,7 +146,7 @@ public class OpenIddictEntityFrameworkApplicationStore<TApplication, TAuthorizat
// 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 = CreateTransaction();
using var transaction = Context.CreateTransaction(IsolationLevel.Serializable);
// Remove all the authorizations associated with the application and
// the tokens attached to these implicit or explicit authorizations.

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

@ -130,19 +130,6 @@ public class OpenIddictEntityFrameworkAuthorizationStore<TAuthorization, TApplic
throw new ArgumentNullException(nameof(authorization));
}
DbContextTransaction? CreateTransaction()
{
try
{
return Context.Database.BeginTransaction(IsolationLevel.Serializable);
}
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
return null;
}
}
Task<List<TToken>> ListTokensAsync()
=> (from token in Tokens
where token.Authorization!.Id!.Equals(authorization.Id)
@ -151,7 +138,7 @@ public class OpenIddictEntityFrameworkAuthorizationStore<TAuthorization, TApplic
// 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 = CreateTransaction();
using var transaction = Context.CreateTransaction(IsolationLevel.Serializable);
// Remove all the tokens associated with the authorization.
var tokens = await ListTokensAsync();
@ -609,22 +596,6 @@ public class OpenIddictEntityFrameworkAuthorizationStore<TAuthorization, TApplic
var result = 0L;
DbContextTransaction? CreateTransaction()
{
// Note: relational providers like Sqlite are known to lack proper support
// for repeatable read transactions. To ensure this method can be safely used
// with such providers, the database transaction is created in a try/catch block.
try
{
return Context.Database.BeginTransaction(IsolationLevel.RepeatableRead);
}
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
return null;
}
}
// Note: to avoid sending too many queries, the maximum number of elements
// that can be removed by a single call to PruneAsync() is deliberately limited.
for (var index = 0; index < 1_000; index++)
@ -635,7 +606,7 @@ public class OpenIddictEntityFrameworkAuthorizationStore<TAuthorization, TApplic
// 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 = CreateTransaction();
using var transaction = Context.CreateTransaction(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.

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

@ -600,22 +600,6 @@ public class OpenIddictEntityFrameworkTokenStore<TToken, TApplication, TAuthoriz
var result = 0L;
DbContextTransaction? CreateTransaction()
{
// Note: relational providers like Sqlite are known to lack proper support
// for repeatable read transactions. To ensure this method can be safely used
// with such providers, the database transaction is created in a try/catch block.
try
{
return Context.Database.BeginTransaction(IsolationLevel.RepeatableRead);
}
catch (Exception exception) when (!OpenIddictHelpers.IsFatal(exception))
{
return null;
}
}
// Note: to avoid sending too many queries, the maximum number of elements
// that can be removed by a single call to PruneAsync() is deliberately limited.
for (var index = 0; index < 1_000; index++)
@ -626,7 +610,7 @@ public class OpenIddictEntityFrameworkTokenStore<TToken, TApplication, TAuthoriz
// 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 = CreateTransaction();
using var transaction = Context.CreateTransaction(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.

Loading…
Cancel
Save