Fix NpgsqlOptionsExtension losing ParameterizedCollectionMode between clones#3796
Fix NpgsqlOptionsExtension losing ParameterizedCollectionMode between clones#3796
Conversation
… clones Add _parameterizedCollectionMode to the copy constructor so the value is preserved when Clone() is called by any WithXyz method. Add test verifying the mode survives a subsequent UsePostgresVersion call. Agent-Logs-Url: https://github.com/npgsql/efcore.pg/sessions/6210ab26-9cbe-4297-b483-d782610e68e9 Co-authored-by: roji <1862641+roji@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Fixes an options-cloning bug in NpgsqlOptionsExtension where ParameterizedCollectionMode was unintentionally reset to default when the extension was cloned (e.g., via subsequent WithXyz option calls), and adds a regression test to ensure the mode is preserved.
Changes:
- Copy
_parameterizedCollectionModeinNpgsqlOptionsExtensioncopy constructor to preserve it across clones. - Add a unit test asserting
ParameterizedCollectionModesurvives an additional options call that triggers cloning.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
src/EFCore.PG/Infrastructure/Internal/NpgsqlOptionsExtension.cs |
Copies _parameterizedCollectionMode in the copy ctor to prevent loss during Clone()/WithXyz chaining. |
test/EFCore.PG.Tests/NpgsqlDbContextOptionsExtensionsTest.cs |
Adds regression coverage asserting the configured ParameterizedCollectionMode remains after a subsequent option mutation. |
| optionsBuilder.UseNpgsql("Database=Crunchie", b => | ||
| { | ||
| b.UseParameterizedCollectionMode(ParameterTranslationMode.MultipleParameters); | ||
| b.UseRelationalNulls(); | ||
| }); |
There was a problem hiding this comment.
The PR description/example references UsePostgresVersion(...), but this repo's public options API appears to be SetPostgresVersion(...) (no UsePostgresVersion found under src/). Consider updating the PR description and/or adjusting this regression test to use SetPostgresVersion so it matches the reported scenario and is easier to understand.
_parameterizedCollectionModewas not copied in theNpgsqlOptionsExtensioncopy constructor, so anyWithXyzcall (which clones internally) would silently reset it to the default._parameterizedCollectionMode = copyFrom._parameterizedCollectionModeto the copy constructor, consistent with all other fieldsParameterizedCollectionMode_is_preserved_after_clonecovering the reported scenarioFixes #3795
Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
80zvsblobprodcus35.vsblob.vsassets.io/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /home/REDACTED/work/efcore.pg/efcore.pg/EFCore.PG.slnx --packages /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true(dns block)/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /home/REDACTED/work/efcore.pg/efcore.pg/test/EFCore.PG.Tests/EFCore.PG.Tests.csproj --packages /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true dcca�� cture/Internal/N--irreversible-delete(dns block)8xbvsblobprodcus382.vsblob.vsassets.io/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /home/REDACTED/work/efcore.pg/efcore.pg/EFCore.PG.slnx --packages /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true(dns block)/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /home/REDACTED/work/efcore.pg/efcore.pg/test/EFCore.PG.FunctionalTests/EFCore.PG.FunctionalTests.csproj --packages /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true dcca��(dns block)i1qvsblobprodcus353.vsblob.vsassets.io/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /home/REDACTED/work/efcore.pg/efcore.pg/EFCore.PG.slnx --packages /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true(dns block)/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /home/REDACTED/work/efcore.pg/efcore.pg/test/EFCore.PG.Tests/EFCore.PG.Tests.csproj --packages /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true dcca�� cture/Internal/N--irreversible-delete(dns block)/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /home/REDACTED/work/efcore.pg/efcore.pg/test/EFCore.PG.FunctionalTests/EFCore.PG.FunctionalTests.csproj --packages /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true dcca��(dns block)jrqvsblobprodcus343.vsblob.vsassets.io/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /home/REDACTED/work/efcore.pg/efcore.pg/EFCore.PG.slnx --packages /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true(dns block)/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /home/REDACTED/work/efcore.pg/efcore.pg/src/EFCore.PG/EFCore.PG.csproj --packages /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true dcca��(dns block)/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /home/REDACTED/work/efcore.pg/efcore.pg/src/EFCore.PG.NodaTime/EFCore.PG.NodaTime.csproj --packages /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true dcca�� cture/Internal/N--irreversible-delete(dns block)p2ovsblobprodcus312.vsblob.vsassets.io/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /home/REDACTED/work/efcore.pg/efcore.pg/EFCore.PG.slnx --packages /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true(dns block)/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /home/REDACTED/work/efcore.pg/efcore.pg/src/EFCore.PG/EFCore.PG.csproj --packages /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true dcca��(dns block)/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /home/REDACTED/work/efcore.pg/efcore.pg/src/EFCore.PG.NodaTime/EFCore.PG.NodaTime.csproj --packages /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true dcca�� cture/Internal/N--irreversible-delete(dns block)rcxvsblobprodcus328.vsblob.vsassets.io/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /home/REDACTED/work/efcore.pg/efcore.pg/EFCore.PG.slnx --packages /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true(dns block)/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /home/REDACTED/work/efcore.pg/efcore.pg/test/EFCore.PG.FunctionalTests/EFCore.PG.FunctionalTests.csproj --packages /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true dcca��(dns block)uy6vsblobprodcus34.vsblob.vsassets.io/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /home/REDACTED/work/efcore.pg/efcore.pg/EFCore.PG.slnx --packages /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true(dns block)/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /home/REDACTED/work/efcore.pg/efcore.pg/test/EFCore.PG.Tests/EFCore.PG.Tests.csproj --packages /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true dcca�� cture/Internal/N--irreversible-delete(dns block)www.myget.org/usr/bin/dotnet dotnet test test/EFCore.PG.Tests --filter FullyQualifiedName~NpgsqlDbContextOptionsExtensionsTest.ParameterizedCollectionMode_is_preserved_after_clone(dns block)/opt/hostedtoolcache/CodeQL/2.24.3/x64/codeql/csharp/tools/linux64/Semmle.Autobuild.CSharp /opt/hostedtoolcache/CodeQL/2.24.3/x64/codeql/csharp/tools/linux64/Semmle.Autobuild.CSharp b3274879af910afc769298a2b2f5c230ece/5d4be8c5d6383d214128a8999c0e11ab23f3ef60a787028b��(dns block)/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/.dotnet/dotnet restore --no-dependencies /home/REDACTED/work/efcore.pg/efcore.pg/EFCore.PG.slnx --packages /tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/packages /p:DisableImplicitNuGetFallbackFolder=true --verbosity normal /p:TargetFrameworkRootPath=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:NetCoreTargetingPackRoot=/tmp/codeql-scratch-a20bfa1f1f244e03/dbs/csharp/working/emptyFakeDotnetRoot /p:AllowMissingPrunePackageData=true(dns block)If you need me to access, download, or install something from one of these locations, you can either: