Skip to content

Commit

Permalink
Add net9.0 support for EFCore components (dotnet#5932)
Browse files Browse the repository at this point in the history
Co-authored-by: Ankit Jain <[email protected]>
  • Loading branch information
sebastienros and radical authored Oct 8, 2024
1 parent 659f58d commit 371eb52
Show file tree
Hide file tree
Showing 24 changed files with 210 additions and 104 deletions.
2 changes: 1 addition & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@
<PackageVersion Include="MySqlConnector.Logging.Microsoft.Extensions.Logging" Version="2.1.0" />
<PackageVersion Include="NATS.Net" Version="2.4.0" />
<PackageVersion Include="Npgsql.DependencyInjection" Version="8.0.4" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.8" />
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="$(NpgsqlEntityFrameworkCorePostgreSQLPackageVersion)" />
<PackageVersion Include="OpenAI" Version="2.0.0" />
<PackageVersion Include="Oracle.EntityFrameworkCore" Version="8.23.50" />
<PackageVersion Include="Oracle.ManagedDataAccess.OpenTelemetry" Version="23.5.0" />
Expand Down
21 changes: 21 additions & 0 deletions eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
-->
<BaselineVersionForPackageValidation>8.0.1</BaselineVersionForPackageValidation>
<DefaultTargetFramework>net8.0</DefaultTargetFramework>
<AllTargetFrameworks>$(DefaultTargetFramework);net9.0</AllTargetFrameworks>
<!-- dotnet 8.0 versions for running tests -->
<DotNetRuntimePreviousVersionForTesting>8.0.8</DotNetRuntimePreviousVersionForTesting>
<!-- dotnet 8.0 versions for running tests - used for workload tests -->
Expand Down Expand Up @@ -66,8 +67,28 @@
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>8.0.8</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
<MicrosoftEntityFrameworkCoreToolsPackageVersion>8.0.8</MicrosoftEntityFrameworkCoreToolsPackageVersion>
<MicrosoftNETRuntimeWorkloadTestingInternalVersion>9.0.0-preview.5.24272.3</MicrosoftNETRuntimeWorkloadTestingInternalVersion>

<NpgsqlEntityFrameworkCorePostgreSQLPackageVersion>8.0.8</NpgsqlEntityFrameworkCorePostgreSQLPackageVersion>
<!-- for templates -->
<MicrosoftExtensionsHttpResiliencePackageVersionForNet8>$(MicrosoftExtensionsHttpResiliencePackageVersion)</MicrosoftExtensionsHttpResiliencePackageVersionForNet8>
<MicrosoftExtensionsHttpResiliencePackageVersionForNet9>$(MicrosoftExtensionsHttpResiliencePackageVersion)</MicrosoftExtensionsHttpResiliencePackageVersionForNet9>
</PropertyGroup>

<PropertyGroup Condition="'$(TargetFramework)' == 'net9.0'">
<!-- Other -->
<MicrosoftExtensionsConfigurationAbstractionsPackageVersion>9.0.0-rc.1.24431.7</MicrosoftExtensionsConfigurationAbstractionsPackageVersion>
<MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>9.0.0-rc.1.24431.7</MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion>
<MicrosoftExtensionsLoggingAbstractionsPackageVersion>9.0.0-rc.1.24431.7</MicrosoftExtensionsLoggingAbstractionsPackageVersion>
<MicrosoftExtensionsOptionsPackageVersion>9.0.0-rc.1.24431.7</MicrosoftExtensionsOptionsPackageVersion>
<MicrosoftExtensionsPrimitivesPackageVersion>9.0.0-rc.1.24431.7</MicrosoftExtensionsPrimitivesPackageVersion>

<!-- EF -->
<MicrosoftEntityFrameworkCoreCosmosPackageVersion>9.0.0-rc.1.24451.1</MicrosoftEntityFrameworkCoreCosmosPackageVersion>
<MicrosoftEntityFrameworkCoreDesignPackageVersion>9.0.0-rc.1.24451.1</MicrosoftEntityFrameworkCoreDesignPackageVersion>
<MicrosoftEntityFrameworkCoreSqlServerPackageVersion>9.0.0-rc.1.24451.1</MicrosoftEntityFrameworkCoreSqlServerPackageVersion>
<MicrosoftEntityFrameworkCoreToolsPackageVersion>9.0.0-rc.1.24451.1</MicrosoftEntityFrameworkCoreToolsPackageVersion>

<NpgsqlEntityFrameworkCorePostgreSQLPackageVersion>9.0.0-rc.1</NpgsqlEntityFrameworkCorePostgreSQLPackageVersion>
</PropertyGroup>

</Project>
1 change: 1 addition & 0 deletions eng/pipelines/templates/BuildAndTest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ steps:
- template: /eng/pipelines/templates/send-to-helix.yml
parameters:
HelixProjectPath: '$(Build.SourcesDirectory)/tests/helix/send-to-helix-ci.proj'
# Code coverage on windows is disabled: <issue>
HelixProjectArguments: /m /p:ContinuousIntegrationBuild=true /p:Configuration=${{ parameters.buildConfig }} /p:RunWithCodeCoverage=true /p:RepoTestResultsPath=${{ parameters.repoTestResultsPath }}

${{ if eq(parameters.isWindows, 'true') }}:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>$(DefaultTargetFramework)</TargetFramework>
<TargetFrameworks>$(AllTargetFrameworks)</TargetFrameworks>
<IsPackable>true</IsPackable>
<PackageTags>$(ComponentEfCorePackageTags) azure cosmos cosmosdb </PackageTags>
<Description>A Microsoft Azure Cosmos DB provider for Entity Framework Core that integrates with Aspire, including connection pooling, logging, and telemetry.</Description>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,21 +133,19 @@ void UseCosmosBody(CosmosDbContextOptionsBuilder builder)

if (settings.RequestTimeout.HasValue)
{
builder.CheckDbContextRegistered<TContext>();

#if NET9_0_OR_GREATER
builder.Services.ConfigureDbContext<TContext>(optionsBuilder =>
{
ConfigureRequestTimeout<TContext>(optionsBuilder, settings);
});
#else
builder.PatchServiceDescriptor<TContext>(optionsBuilder =>
{
#pragma warning disable EF1001 // Internal EF Core API usage.
var extension = optionsBuilder.Options.FindExtension<CosmosOptionsExtension>();

if (extension != null &&
extension.RequestTimeout.HasValue &&
extension.RequestTimeout != settings.RequestTimeout)
{
throw new InvalidOperationException($"Conflicting values for 'RequestTimeout' were found in {nameof(EntityFrameworkCoreCosmosSettings)} and set in DbContextOptions<{typeof(TContext).Name}>.");
}

extension?.WithRequestTimeout(settings.RequestTimeout);
#pragma warning restore EF1001 // Internal EF Core API usage.
ConfigureRequestTimeout<TContext>(optionsBuilder, settings);
});
#endif
}
else
{
Expand All @@ -157,6 +155,22 @@ void UseCosmosBody(CosmosDbContextOptionsBuilder builder)
ConfigureInstrumentation<TContext>(builder, settings);
}

private static void ConfigureRequestTimeout<TContext>(DbContextOptionsBuilder builder, EntityFrameworkCoreCosmosSettings settings)
{
#pragma warning disable EF1001 // Internal EF Core API usage.
var extension = builder.Options.FindExtension<CosmosOptionsExtension>();

if (extension != null &&
extension.RequestTimeout.HasValue &&
extension.RequestTimeout != settings.RequestTimeout)
{
throw new InvalidOperationException($"Conflicting values for 'RequestTimeout' were found in {nameof(EntityFrameworkCoreCosmosSettings)} and set in DbContextOptions<{typeof(TContext).Name}>.");
}

extension?.WithRequestTimeout(settings.RequestTimeout);
#pragma warning restore EF1001 // Internal EF Core API usage.
}

private static void ConfigureInstrumentation<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicProperties)] TContext>(IHostApplicationBuilder builder, EntityFrameworkCoreCosmosSettings settings) where TContext : DbContext
{
if (!settings.DisableTracing)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>$(DefaultTargetFramework)</TargetFramework>
<TargetFrameworks>$(AllTargetFrameworks)</TargetFrameworks>
<IsPackable>true</IsPackable>
<PackageTags>$(ComponentEfCorePackageTags) sqlserver sql</PackageTags>
<Description>A Microsoft SQL Server provider for Entity Framework Core that integrates with Aspire, including connection pooling, health check, logging, and telemetry.</Description>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,15 @@ void ConfigureRetry()
#pragma warning disable EF1001 // Internal EF Core API usage.
if (!settings.DisableRetry || settings.CommandTimeout.HasValue)
{
builder.CheckDbContextRegistered<TContext>();

#if NET9_0_OR_GREATER
builder.Services.ConfigureDbContext<TContext>(optionsBuilder => optionsBuilder.ConfigureSqlEngine(options =>
{
#else
builder.PatchServiceDescriptor<TContext>(optionsBuilder => optionsBuilder.UseSqlServer(options =>
{
#endif
var extension = optionsBuilder.Options.FindExtension<SqlServerOptionsExtension>();

if (!settings.DisableRetry)
Expand Down Expand Up @@ -159,8 +166,8 @@ void ConfigureRetry()
}
}));
}
#pragma warning restore EF1001 // Internal EF Core API usage.
}
#pragma warning restore EF1001 // Internal EF Core API usage.
}

private static void ConfigureInstrumentation<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors | DynamicallyAccessedMemberTypes.PublicProperties)] TContext>(IHostApplicationBuilder builder, MicrosoftEntityFrameworkCoreSqlServerSettings settings) where TContext : DbContext
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>$(DefaultTargetFramework)</TargetFramework>
<TargetFrameworks>$(AllTargetFrameworks)</TargetFrameworks>
<IsPackable>true</IsPackable>
<PackageTags>$(ComponentEfCorePackageTags) postgressql postgres npgsql sql</PackageTags>
<Description>A PostgreSQL® provider for Entity Framework Core that integrates with Aspire, including connection pooling, health checks, logging, and telemetry.</Description>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,53 +124,64 @@ void ConfigureRetry()
#pragma warning disable EF1001 // Internal EF Core API usage.
if (!settings.DisableRetry || settings.CommandTimeout.HasValue)
{
builder.PatchServiceDescriptor<TContext>(optionsBuilder => optionsBuilder.UseNpgsql(options =>
{
var extension = optionsBuilder.Options.FindExtension<NpgsqlOptionsExtension>();
builder.CheckDbContextRegistered<TContext>();

#if NET9_0_OR_GREATER
builder.Services.ConfigureDbContext<TContext>(ConfigureRetryAndTimeout);
#else
builder.PatchServiceDescriptor<TContext>(ConfigureRetryAndTimeout);
#endif

if (!settings.DisableRetry)
void ConfigureRetryAndTimeout(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseNpgsql(options =>
{
var executionStrategy = extension?.ExecutionStrategyFactory?.Invoke(new ExecutionStrategyDependencies(null!, optionsBuilder.Options, null!));
var extension = optionsBuilder.Options.FindExtension<NpgsqlOptionsExtension>();

if (executionStrategy != null)
if (!settings.DisableRetry)
{
if (executionStrategy is NpgsqlRetryingExecutionStrategy)
{
// Keep custom Retry strategy.
// Any sub-class of NpgsqlRetryingExecutionStrategy is a valid retry strategy
// which shouldn't be replaced even with DisableRetry == false
}
else if (executionStrategy.GetType() != typeof(NpgsqlExecutionStrategy))
{
// Check NpgsqlExecutionStrategy specifically (no 'is'), any sub-class is treated as a custom strategy.
var executionStrategy = extension?.ExecutionStrategyFactory?.Invoke(new ExecutionStrategyDependencies(null!, optionsBuilder.Options, null!));

throw new InvalidOperationException($"{nameof(NpgsqlEntityFrameworkCorePostgreSQLSettings)}.{nameof(NpgsqlEntityFrameworkCorePostgreSQLSettings.DisableRetry)} needs to be set when a custom Execution Strategy is configured.");
if (executionStrategy != null)
{
if (executionStrategy is NpgsqlRetryingExecutionStrategy)
{
// Keep custom Retry strategy.
// Any sub-class of NpgsqlRetryingExecutionStrategy is a valid retry strategy
// which shouldn't be replaced even with DisableRetry == false
}
else if (executionStrategy.GetType() != typeof(NpgsqlExecutionStrategy))
{
// Check NpgsqlExecutionStrategy specifically (no 'is'), any sub-class is treated as a custom strategy.

throw new InvalidOperationException($"{nameof(NpgsqlEntityFrameworkCorePostgreSQLSettings)}.{nameof(NpgsqlEntityFrameworkCorePostgreSQLSettings.DisableRetry)} needs to be set when a custom Execution Strategy is configured.");
}
else
{
options.EnableRetryOnFailure();
}
}
else
{
options.EnableRetryOnFailure();
}
}
else
{
options.EnableRetryOnFailure();
}
}

if (settings.CommandTimeout.HasValue)
{
if (extension != null &&
extension.CommandTimeout.HasValue &&
extension.CommandTimeout != settings.CommandTimeout)
if (settings.CommandTimeout.HasValue)
{
throw new InvalidOperationException($"Conflicting values for 'CommandTimeout' were found in {nameof(NpgsqlEntityFrameworkCorePostgreSQLSettings)} and set in DbContextOptions<{typeof(TContext).Name}>.");
}
if (extension != null &&
extension.CommandTimeout.HasValue &&
extension.CommandTimeout != settings.CommandTimeout)
{
throw new InvalidOperationException($"Conflicting values for 'CommandTimeout' were found in {nameof(NpgsqlEntityFrameworkCorePostgreSQLSettings)} and set in DbContextOptions<{typeof(TContext).Name}>.");
}

options.CommandTimeout(settings.CommandTimeout);
}
}));
}
options.CommandTimeout(settings.CommandTimeout);
}
});
}
#pragma warning restore EF1001 // Internal EF Core API usage.
}
}
}

Expand Down
Loading

0 comments on commit 371eb52

Please sign in to comment.