Skip to content

Commit 571cd73

Browse files
committed
fix: Centralize EF Core provider names and improve executor config
Introduce ProviderName class to centralize EF Core provider name constants, replacing scattered string literals and private constants. Update all provider selection logic to use these constants. Refactor OutboxOperationsExecutor constructors to accept maxDegreeOfParallelism for improved concurrency control. Enhance maintainability and reduce errors in provider-specific logic.
1 parent 9002689 commit 571cd73

7 files changed

Lines changed: 59 additions & 47 deletions

src/NetEvolve.Pulse.EntityFramework/ModelBuilderExtensions.cs

Lines changed: 7 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,37 +12,6 @@
1212
/// </summary>
1313
public static class ModelBuilderExtensions
1414
{
15-
/// <summary>
16-
/// The provider name for the EF Core InMemory provider (<c>Microsoft.EntityFrameworkCore.InMemory</c>).
17-
/// Intended for testing only.
18-
/// </summary>
19-
private const string InMemoryProviderName = "Microsoft.EntityFrameworkCore.InMemory";
20-
21-
/// <summary>
22-
/// The provider name for Npgsql (PostgreSQL).
23-
/// </summary>
24-
private const string NpgsqlProviderName = "Npgsql.EntityFrameworkCore.PostgreSQL";
25-
26-
/// <summary>
27-
/// The provider name for Microsoft.EntityFrameworkCore.Sqlite.
28-
/// </summary>
29-
private const string SqliteProviderName = "Microsoft.EntityFrameworkCore.Sqlite";
30-
31-
/// <summary>
32-
/// The provider name for Microsoft.EntityFrameworkCore.SqlServer.
33-
/// </summary>
34-
private const string SqlServerProviderName = "Microsoft.EntityFrameworkCore.SqlServer";
35-
36-
/// <summary>
37-
/// The provider name for Pomelo MySQL (<c>Pomelo.EntityFrameworkCore.MySql</c>).
38-
/// </summary>
39-
private const string PomeloMySqlProviderName = "Pomelo.EntityFrameworkCore.MySql";
40-
41-
/// <summary>
42-
/// The provider name for the Oracle MySQL provider (<c>MySql.EntityFrameworkCore</c>).
43-
/// </summary>
44-
private const string OracleMySqlProviderName = "MySql.EntityFrameworkCore";
45-
4615
/// <summary>
4716
/// Applies all Pulse-related entity configurations to the model builder.
4817
/// </summary>
@@ -98,11 +67,13 @@ private static IEntityTypeConfiguration<OutboxMessage> GetOutboxConfiguration<TC
9867
resolvedOptions ??= Options.Create(new OutboxOptions());
9968
return providerName switch
10069
{
101-
NpgsqlProviderName => new PostgreSqlOutboxMessageConfiguration(resolvedOptions),
102-
SqliteProviderName => new SqliteOutboxMessageConfiguration(resolvedOptions),
103-
SqlServerProviderName => new SqlServerOutboxMessageConfiguration(resolvedOptions),
104-
PomeloMySqlProviderName or OracleMySqlProviderName => new MySqlOutboxMessageConfiguration(resolvedOptions),
105-
InMemoryProviderName => new InMemoryOutboxMessageConfiguration(resolvedOptions),
70+
ProviderName.Npgsql => new PostgreSqlOutboxMessageConfiguration(resolvedOptions),
71+
ProviderName.Sqlite => new SqliteOutboxMessageConfiguration(resolvedOptions),
72+
ProviderName.SqlServer => new SqlServerOutboxMessageConfiguration(resolvedOptions),
73+
ProviderName.PomeloMySql or ProviderName.OracleMySql => new MySqlOutboxMessageConfiguration(
74+
resolvedOptions
75+
),
76+
ProviderName.InMemory => new InMemoryOutboxMessageConfiguration(resolvedOptions),
10677
_ => throw new NotSupportedException($"Unsupported EF Core provider: {providerName}"),
10778
};
10879
}

src/NetEvolve.Pulse.EntityFramework/Outbox/BulkOutboxOperationsExecutor.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ namespace NetEvolve.Pulse.Outbox;
1313
/// (SQL Server, PostgreSQL, SQLite, and others).
1414
/// </remarks>
1515
/// <typeparam name="TContext">The DbContext type that implements <see cref="IOutboxDbContext"/>.</typeparam>
16-
internal sealed class BulkOutboxOperationsExecutor<TContext>(TContext context) : IOutboxOperationsExecutor
16+
internal sealed class BulkOutboxOperationsExecutor<TContext>(TContext context, int maxDegreeOfParallelism)
17+
: IOutboxOperationsExecutor
1718
where TContext : DbContext, IOutboxDbContext
1819
{
19-
private readonly SemaphoreSlim _semaphore = new(1, 1);
20+
private readonly SemaphoreSlim _semaphore = new(maxDegreeOfParallelism, maxDegreeOfParallelism);
2021
private bool _disposedValue;
2122

2223
/// <inheritdoc />

src/NetEvolve.Pulse.EntityFramework/Outbox/EntityFrameworkOutboxRepository.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,12 @@ public EntityFrameworkOutboxRepository(TContext context, TimeProvider timeProvid
4747
_executor = context.Database.ProviderName switch
4848
{
4949
// InMemory does not support ExecuteUpdate/ExecuteDelete at all.
50-
"Microsoft.EntityFrameworkCore.InMemory" => new InMemoryOutboxOperationsExecutor<TContext>(context),
50+
ProviderName.InMemory => new InMemoryOutboxOperationsExecutor<TContext>(context, 1),
5151
// Oracle MySQL cannot apply value converters in ExecuteUpdateAsync parameters and
5252
// cannot translate a parameterised Guid collection into a SQL IN clause.
53-
"MySql.EntityFrameworkCore" => new MySqlOutboxOperationsExecutor<TContext>(context),
54-
_ => new BulkOutboxOperationsExecutor<TContext>(context),
53+
ProviderName.OracleMySql => new MySqlOutboxOperationsExecutor<TContext>(context, 1),
54+
ProviderName.Npgsql => new BulkOutboxOperationsExecutor<TContext>(context, 1),
55+
_ => new BulkOutboxOperationsExecutor<TContext>(context, Environment.ProcessorCount - 1),
5556
};
5657
}
5758

src/NetEvolve.Pulse.EntityFramework/Outbox/InMemoryOutboxOperationsExecutor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ namespace NetEvolve.Pulse.Outbox;
1414
/// <see cref="TrackingOutboxOperationsExecutorBase{TContext}"/>).
1515
/// </remarks>
1616
/// <typeparam name="TContext">The DbContext type that implements <see cref="IOutboxDbContext"/>.</typeparam>
17-
internal sealed class InMemoryOutboxOperationsExecutor<TContext>(TContext context)
18-
: TrackingOutboxOperationsExecutorBase<TContext>(context)
17+
internal sealed class InMemoryOutboxOperationsExecutor<TContext>(TContext context, int maxDegreeOfParallelism)
18+
: TrackingOutboxOperationsExecutorBase<TContext>(context, maxDegreeOfParallelism)
1919
where TContext : DbContext, IOutboxDbContext
2020
{
2121
/// <inheritdoc />

src/NetEvolve.Pulse.EntityFramework/Outbox/MySqlOutboxOperationsExecutor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ namespace NetEvolve.Pulse.Outbox;
2727
/// cache for entities already loaded by <c>FetchAndMarkAsync</c>.
2828
/// </remarks>
2929
/// <typeparam name="TContext">The DbContext type that implements <see cref="IOutboxDbContext"/>.</typeparam>
30-
internal sealed class MySqlOutboxOperationsExecutor<TContext>(TContext context)
31-
: TrackingOutboxOperationsExecutorBase<TContext>(context)
30+
internal sealed class MySqlOutboxOperationsExecutor<TContext>(TContext context, int maxDegreeOfParallelism)
31+
: TrackingOutboxOperationsExecutorBase<TContext>(context, maxDegreeOfParallelism)
3232
where TContext : DbContext, IOutboxDbContext
3333
{
3434
/// <inheritdoc />

src/NetEvolve.Pulse.EntityFramework/Outbox/TrackingOutboxOperationsExecutorBase.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ namespace NetEvolve.Pulse.Outbox;
1414
/// Derived classes only need to implement <see cref="UpdateByIdsAsync"/>, which varies by provider.
1515
/// </remarks>
1616
/// <typeparam name="TContext">The DbContext type that implements <see cref="IOutboxDbContext"/>.</typeparam>
17-
internal abstract class TrackingOutboxOperationsExecutorBase<TContext>(TContext context) : IOutboxOperationsExecutor
17+
internal abstract class TrackingOutboxOperationsExecutorBase<TContext>(TContext context, int maxDegreeOfParallelism)
18+
: IOutboxOperationsExecutor
1819
where TContext : DbContext, IOutboxDbContext
1920
{
2021
/// <summary>The DbContext used for all tracking-based query and update operations.</summary>
2122
protected readonly TContext _context = context;
2223

23-
protected readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
24+
protected readonly SemaphoreSlim _semaphore = new SemaphoreSlim(maxDegreeOfParallelism, maxDegreeOfParallelism);
2425
private bool _disposedValue;
2526

2627
/// <inheritdoc />
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
namespace NetEvolve.Pulse;
2+
3+
/// <summary>
4+
/// Static class containing constants for supported EF Core provider names, used for provider-specific
5+
/// </summary>
6+
internal static class ProviderName
7+
{
8+
/// <summary>
9+
/// The provider name for the EF Core InMemory provider (<c>Microsoft.EntityFrameworkCore.InMemory</c>).
10+
/// Intended for testing only.
11+
/// </summary>
12+
internal const string InMemory = "Microsoft.EntityFrameworkCore.InMemory";
13+
14+
/// <summary>
15+
/// The provider name for Npgsql (PostgreSQL).
16+
/// </summary>
17+
internal const string Npgsql = "Npgsql.EntityFrameworkCore.PostgreSQL";
18+
19+
/// <summary>
20+
/// The provider name for Microsoft.EntityFrameworkCore.Sqlite.
21+
/// </summary>
22+
internal const string Sqlite = "Microsoft.EntityFrameworkCore.Sqlite";
23+
24+
/// <summary>
25+
/// The provider name for Microsoft.EntityFrameworkCore.SqlServer.
26+
/// </summary>
27+
internal const string SqlServer = "Microsoft.EntityFrameworkCore.SqlServer";
28+
29+
/// <summary>
30+
/// The provider name for Pomelo MySQL (<c>Pomelo.EntityFrameworkCore.MySql</c>).
31+
/// </summary>
32+
internal const string PomeloMySql = "Pomelo.EntityFrameworkCore.MySql";
33+
34+
/// <summary>
35+
/// The provider name for the Oracle MySQL provider (<c>MySql.EntityFrameworkCore</c>).
36+
/// </summary>
37+
internal const string OracleMySql = "MySql.EntityFrameworkCore";
38+
}

0 commit comments

Comments
 (0)