-
Notifications
You must be signed in to change notification settings - Fork 715
Add Enrich EF API #2125
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Enrich EF API #2125
Conversation
# Conflicts: # src/Components/Aspire.Npgsql.EntityFrameworkCore.PostgreSQL/AspireEFPostgreSqlExtensions.cs
b7695d8 to
a76069d
Compare
| "type": "string", | ||
| "description": "Gets or sets the connection string of the PostgreSQL database to connect to." | ||
| }, | ||
| "DbContextPooling": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pooling is enabled by default in AddNpgsql. Use Enrich otherwise.
| "description": "Gets or sets a boolean value that indicates whether the OpenTelemetry metrics are enabled or not.", | ||
| "default": true | ||
| }, | ||
| "Retry": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bool instead of int to simplify the usage. Use a custom call in the options builder to define a custom value.
| namespace Aspire.Components.Common.Tests; | ||
|
|
||
| public class TestDbContext : DbContext | ||
| public interface ITestDbContext |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To test we can register and Enrich a DbContext with distinct service and implementation.
| configureSettings?.Invoke(settings); | ||
|
|
||
| if (settings.DbContextPooling) | ||
| builder.Services.AddNpgsqlDataSource(settings.ConnectionString ?? string.Empty, builder => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are overwriting my changes in ae11632. Can you revert this so it doesn't add back NpgsqlDataSource into DI?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
|
||
| // We don't provide the connection string, it's going to use the pre-registered DataSource. | ||
| // We don't register logger factory, because there is no need to: https://learn.microsoft.com/dotnet/api/microsoft.entityframeworkcore.dbcontextoptionsbuilder.useloggerfactory?view=efcore-7.0#remarks | ||
| dbContextOptionsBuilder.UseNpgsql(builder => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you always need to call UseNpgsql whether settings.Retry is true or false.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, mistake when I refactored the code to reuse the same method for both Enrich and AddNpgsql. And with your changes I might have to split them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It also means we might be missing a test that should have caught that for AddNpgsql.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It also means we might be missing a test that should have caught that for AddNpgsql.
Good call. #2136
src/Components/Aspire.Npgsql.EntityFrameworkCore.PostgreSQL/AspireEFPostgreSqlExtensions.cs
Outdated
Show resolved
Hide resolved
src/Components/Aspire.Npgsql.EntityFrameworkCore.PostgreSQL/AspireEFPostgreSqlExtensions.cs
Outdated
Show resolved
Hide resolved
| } | ||
|
|
||
| [Fact] | ||
| public void EnrichCanConfigureDbContextOptions() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(nit) Why are these tests here, and not in EnrichNpgsqlTests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The class was named AspireEFPostgreSqlExtensionsTests.cs which is where they are. Didn't think we would do a test class for a specific method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't realize you meant the one that just got created, moved them.
|
|
||
| protected override void SetupConnectionInformationIsDelayValidated() | ||
| { | ||
| throw new SkipTestException("Need to skip this test until https://github.com/npgsql/efcore.pg/issues/2891 is fixed."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be able to remove this now that we have builder.EnableServiceProviderCaching(false); in ConfigureDbContextOptionsBuilderForTesting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That works, but I had to add a similar thing for Enrich instead since it doesn't care about the connection string.
src/Components/Aspire.Npgsql.EntityFrameworkCore.PostgreSQL/AspireEFPostgreSqlExtensions.cs
Outdated
Show resolved
Hide resolved
src/Components/Aspire.Npgsql.EntityFrameworkCore.PostgreSQL/AspireEFPostgreSqlExtensions.cs
Outdated
Show resolved
Hide resolved
|
Add a playground sample or modify one with the new apai |
| #pragma warning restore EF1001 // Internal EF Core API usage. | ||
| } | ||
|
|
||
| public class WorkaroundToReadProtectedField : NpgsqlRetryingExecutionStrategy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(nit) maybe we can extract this to a common class to share it.
|
|
||
| builder.EnrichNpgsqlDbContext<TestDbContext>(); | ||
|
|
||
| // The service descriptor should not be affected with MaxRetryCount set to 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does with MaxRetryCount set to 0 mean here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Forgot to change the text, will fix. The idea is that if the setting is false (0 previously) then we should not have replaced the service descriptor.
|
@davidfowl example added in README and in the Postgres playground. |
| internal static void ConfigureDbContextOptionsBuilderForTesting(DbContextOptionsBuilder builder) | ||
| { | ||
| // Don't cache the service provider in testing. | ||
| // Works around https://github.com/npgsql/efcore.pg/issues/2891, which is errantly caches connection strings across DI containers. | ||
| builder.EnableServiceProviderCaching(false); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| internal static void ConfigureDbContextOptionsBuilderForTesting(DbContextOptionsBuilder builder) | |
| { | |
| // Don't cache the service provider in testing. | |
| // Works around https://github.com/npgsql/efcore.pg/issues/2891, which is errantly caches connection strings across DI containers. | |
| builder.EnableServiceProviderCaching(false); | |
| } |
Can we reuse the one from AspireEFPostgreSqlExtensionsTests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thanks for the great work here.
| => Assert.True(new NpgsqlEntityFrameworkCorePostgreSQLSettings().Metrics); | ||
|
|
||
| [Fact] | ||
| public void MaxRetryCountIsSameAsInTheDefaultNpgsqlPolicy() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although I don't think these are super valuable tests, following the current example we should have one that ensures Retry is true by default.
| Assert.Equal(ConnectionString, actualConnectionString); | ||
|
|
||
| // ensure the max retry count from config was respected | ||
| Assert.NotNull(extension.ExecutionStrategyFactory); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment above this line needs to be updated.
| Assert.Equal(new WorkaroundToReadProtectedField(dbContext).RetryCount, new NpgsqlEntityFrameworkCorePostgreSQLSettings().MaxRetryCount); | ||
| } | ||
|
|
||
| public class WorkaroundToReadProtectedField : NpgsqlRetryingExecutionStrategy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be replaced by the common one now. Or just removed since it isn't used anymore.
| NpgsqlEntityFrameworkCorePostgreSQLSettings settings = new(); | ||
| var typeSpecificSectionName = $"{DefaultConfigSectionName}:{typeof(TContext).Name}"; | ||
| var typeSpecificConfigurationSection = builder.Configuration.GetSection(typeSpecificSectionName); | ||
| if (typeSpecificConfigurationSection.Exists()) // https://github.com/dotnet/runtime/issues/91380 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we extract this into a common method?
| return; | ||
| } | ||
|
|
||
| // Resolving DbContext<TContextService> will resolve DbContextOptions<TContextImplementation>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I understand the significance of this line. What exactly does it mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a reminder that we seek the service descriptor for DbContextOptions<TestDbContext> (referenced as TContextImplementation in EF APIs) because it is the db context options that is resolved even when we register a db context with an interface (TContextService in EF APIs)
| // ensure the command timeout was respected | ||
| Assert.Equal(123, extension.CommandTimeout); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need the command timeout 123 stuff in these lower tests? Is it necessary?
| // ensure the command timeout was respected | ||
| Assert.Equal(123, extension.CommandTimeout); | ||
|
|
||
| // ensure the max retry count from config was respected |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // ensure the max retry count from config was respected | |
| // ensure the Retry from config was respected |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Repeated elsewhere.
| # Aspire.Npgsql.EntityFrameworkCore.PostgreSQL library | ||
|
|
||
| Registers [EntityFrameworkCore](https://learn.microsoft.com/ef/core/) [DbContext](https://learn.microsoft.com/dotnet/api/microsoft.entityframeworkcore.dbcontext) in the DI container for connecting PostgreSQL®* database. Enables connection pooling, health check, logging and telemetry. | ||
| Registers [EntityFrameworkCore](https://learn.microsoft.com/ef/core/) [DbContext](https://learn.microsoft.com/dotnet/api/microsoft.entityframeworkcore.dbcontext) in the DI container for connecting PostgreSQL®* database. Enables connection pooling, connection retries, health check, logging and telemetry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| Registers [EntityFrameworkCore](https://learn.microsoft.com/ef/core/) [DbContext](https://learn.microsoft.com/dotnet/api/microsoft.entityframeworkcore.dbcontext) in the DI container for connecting PostgreSQL®* database. Enables connection pooling, connection retries, health check, logging and telemetry. | |
| Registers [EntityFrameworkCore](https://learn.microsoft.com/ef/core/) [DbContext](https://learn.microsoft.com/dotnet/api/microsoft.entityframeworkcore.dbcontext) in the DI container for connecting PostgreSQL®* database. Enables connection pooling, retries, health check, logging and telemetry. |
Retries in general, right?
|
Did we update one of the playground samples? |
|
@davidfowl yes |
Fixes #1403
Microsoft Reviewers: Open in CodeFlow