Skip to content

Commit 6b3ca68

Browse files
rojiNinoFloris
andauthored
Major work around DbDataSource management, enum handling and plugins (npgsql#3167)
Fixes npgsql#2891 Fixes npgsql#3063 Fixes npgsql#1026 Co-authored-by: Nino Floris <[email protected]>
1 parent d5de631 commit 6b3ca68

File tree

57 files changed

+3386
-355
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+3386
-355
lines changed

EFCore.PG.sln

-15
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore.PG.Tests", "test\EFC
2323
EndProject
2424
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore.PG.FunctionalTests", "test\EFCore.PG.FunctionalTests\EFCore.PG.FunctionalTests.csproj", "{05A7D0B7-4AE1-4BC8-A1BE-2389F1593B2D}"
2525
EndProject
26-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore.PG.NodaTime.FunctionalTests", "test\EFCore.PG.NodaTime.FunctionalTests\EFCore.PG.NodaTime.FunctionalTests.csproj", "{B78A7825-BE72-4509-B0AD-01EEC67A9624}"
27-
EndProject
2826
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore.PG.NodaTime", "src\EFCore.PG.NodaTime\EFCore.PG.NodaTime.csproj", "{77F0608F-6D0C-481C-9108-D5176E2EAD69}"
2927
EndProject
3028
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFCore.PG.NTS", "src\EFCore.PG.NTS\EFCore.PG.NTS.csproj", "{D7106D61-C7CA-4005-B31F-43281BB397AD}"
@@ -70,18 +68,6 @@ Global
7068
{05A7D0B7-4AE1-4BC8-A1BE-2389F1593B2D}.Release|Any CPU.Build.0 = Release|Any CPU
7169
{05A7D0B7-4AE1-4BC8-A1BE-2389F1593B2D}.Release|x64.ActiveCfg = Release|Any CPU
7270
{05A7D0B7-4AE1-4BC8-A1BE-2389F1593B2D}.Release|x86.ActiveCfg = Release|Any CPU
73-
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
74-
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Debug|Any CPU.Build.0 = Debug|Any CPU
75-
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Debug|x64.ActiveCfg = Debug|Any CPU
76-
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Debug|x64.Build.0 = Debug|Any CPU
77-
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Debug|x86.ActiveCfg = Debug|Any CPU
78-
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Debug|x86.Build.0 = Debug|Any CPU
79-
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Release|Any CPU.ActiveCfg = Release|Any CPU
80-
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Release|Any CPU.Build.0 = Release|Any CPU
81-
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Release|x64.ActiveCfg = Release|Any CPU
82-
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Release|x64.Build.0 = Release|Any CPU
83-
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Release|x86.ActiveCfg = Release|Any CPU
84-
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Release|x86.Build.0 = Release|Any CPU
8571
{77F0608F-6D0C-481C-9108-D5176E2EAD69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
8672
{77F0608F-6D0C-481C-9108-D5176E2EAD69}.Debug|Any CPU.Build.0 = Debug|Any CPU
8773
{77F0608F-6D0C-481C-9108-D5176E2EAD69}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -114,7 +100,6 @@ Global
114100
{FADDA2D1-03B4-4DEF-8D24-DD1CA4E81F4A} = {8537E50E-CF7F-49CB-B4EF-3E2A1B11F050}
115101
{E1D99AD4-D88B-42BA-86DF-90B98B2E9A01} = {ED612DB1-AB32-4603-95E7-891BACA71C39}
116102
{05A7D0B7-4AE1-4BC8-A1BE-2389F1593B2D} = {ED612DB1-AB32-4603-95E7-891BACA71C39}
117-
{B78A7825-BE72-4509-B0AD-01EEC67A9624} = {ED612DB1-AB32-4603-95E7-891BACA71C39}
118103
{77F0608F-6D0C-481C-9108-D5176E2EAD69} = {8537E50E-CF7F-49CB-B4EF-3E2A1B11F050}
119104
{D7106D61-C7CA-4005-B31F-43281BB397AD} = {8537E50E-CF7F-49CB-B4EF-3E2A1B11F050}
120105
{26203F54-A3C1-43AD-A101-8F589D2D67AD} = {4A5A60DD-41B6-40BF-B677-227A921ECCC8}

src/EFCore.PG.NTS/Design/Internal/NpgsqlNetTopologySuiteDesignTimeServices.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,5 @@ public virtual void ConfigureDesignTimeServices(IServiceCollection serviceCollec
2525
=> serviceCollection
2626
.AddSingleton<IRelationalTypeMappingSourcePlugin, NpgsqlNetTopologySuiteTypeMappingSourcePlugin>()
2727
.AddSingleton<IProviderCodeGeneratorPlugin, NpgsqlNetTopologySuiteCodeGeneratorPlugin>()
28-
.TryAddSingleton<INpgsqlNetTopologySuiteOptions, NpgsqlNetTopologySuiteOptions>();
28+
.TryAddSingleton<INpgsqlNetTopologySuiteSingletonOptions, NpgsqlNetTopologySuiteSingletonOptions>();
2929
}

src/EFCore.PG.NTS/Extensions/NpgsqlNetTopologySuiteDbContextOptionsBuilderExtensions.cs

+15-8
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,26 @@ public static NpgsqlDbContextOptionsBuilder UseNetTopologySuite(
2222
Ordinates handleOrdinates = Ordinates.None,
2323
bool geographyAsDefault = false)
2424
{
25-
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
26-
27-
// TODO: Global-only setup at the ADO.NET level for now, optionally allow per-connection?
28-
#pragma warning disable CS0618 // NpgsqlConnection.GlobalTypeMapper is obsolete
29-
NpgsqlConnection.GlobalTypeMapper.UseNetTopologySuite(
30-
coordinateSequenceFactory, precisionModel, handleOrdinates, geographyAsDefault);
31-
#pragma warning restore CS0618
32-
3325
var coreOptionsBuilder = ((IRelationalDbContextOptionsBuilderInfrastructure)optionsBuilder).OptionsBuilder;
3426

3527
var extension = coreOptionsBuilder.Options.FindExtension<NpgsqlNetTopologySuiteOptionsExtension>()
3628
?? new NpgsqlNetTopologySuiteOptionsExtension();
3729

30+
if (coordinateSequenceFactory is not null)
31+
{
32+
extension = extension.WithCoordinateSequenceFactory(coordinateSequenceFactory);
33+
}
34+
35+
if (precisionModel is not null)
36+
{
37+
extension = extension.WithPrecisionModel(precisionModel);
38+
}
39+
40+
if (handleOrdinates is not Ordinates.None)
41+
{
42+
extension = extension.WithHandleOrdinates(handleOrdinates);
43+
}
44+
3845
if (geographyAsDefault)
3946
{
4047
extension = extension.WithGeographyDefault();

src/EFCore.PG.NTS/Extensions/NpgsqlNetTopologySuiteServiceCollectionExtensions.cs

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure;
12
using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.Internal;
23
using Npgsql.EntityFrameworkCore.PostgreSQL.Internal;
34
using Npgsql.EntityFrameworkCore.PostgreSQL.Query.ExpressionTranslators.Internal;
@@ -21,15 +22,16 @@ public static IServiceCollection AddEntityFrameworkNpgsqlNetTopologySuite(
2122
{
2223
Check.NotNull(serviceCollection, nameof(serviceCollection));
2324

24-
new EntityFrameworkRelationalServicesBuilder(serviceCollection)
25-
.TryAdd<ISingletonOptions, INpgsqlNetTopologySuiteOptions>(p => p.GetRequiredService<INpgsqlNetTopologySuiteOptions>())
25+
new EntityFrameworkNpgsqlServicesBuilder(serviceCollection)
26+
.TryAdd<INpgsqlDataSourceConfigurationPlugin, NetTopologySuiteDataSourceConfigurationPlugin>()
27+
.TryAdd<ISingletonOptions, INpgsqlNetTopologySuiteSingletonOptions>(p => p.GetRequiredService<INpgsqlNetTopologySuiteSingletonOptions>())
2628
.TryAdd<IRelationalTypeMappingSourcePlugin, NpgsqlNetTopologySuiteTypeMappingSourcePlugin>()
2729
.TryAdd<IMethodCallTranslatorPlugin, NpgsqlNetTopologySuiteMethodCallTranslatorPlugin>()
2830
.TryAdd<IAggregateMethodCallTranslatorPlugin, NpgsqlNetTopologySuiteAggregateMethodCallTranslatorPlugin>()
2931
.TryAdd<IMemberTranslatorPlugin, NpgsqlNetTopologySuiteMemberTranslatorPlugin>()
3032
.TryAdd<IConventionSetPlugin, NpgsqlNetTopologySuiteConventionSetPlugin>()
3133
.TryAddProviderSpecificServices(
32-
x => x.TryAddSingleton<INpgsqlNetTopologySuiteOptions, NpgsqlNetTopologySuiteOptions>());
34+
x => x.TryAddSingleton<INpgsqlNetTopologySuiteSingletonOptions, NpgsqlNetTopologySuiteSingletonOptions>());
3335

3436
return serviceCollection;
3537
}

src/EFCore.PG.NTS/Infrastructure/Internal/INpgsqlNetTopologySuiteOptions.cs

-14
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// ReSharper disable once CheckNamespace
2+
3+
namespace Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.Internal;
4+
5+
/// <summary>
6+
/// Represents options for Npgsql NetTopologySuite that can only be set at the <see cref="System.IServiceProvider" /> singleton level.
7+
/// </summary>
8+
public interface INpgsqlNetTopologySuiteSingletonOptions : ISingletonOptions
9+
{
10+
/// <summary>
11+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
12+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
13+
/// any release. You should only use it directly in your code with extreme caution and knowing that
14+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
15+
/// </summary>
16+
CoordinateSequenceFactory? CoordinateSequenceFactory { get; }
17+
18+
/// <summary>
19+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
20+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
21+
/// any release. You should only use it directly in your code with extreme caution and knowing that
22+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
23+
/// </summary>
24+
PrecisionModel? PrecisionModel { get; }
25+
26+
/// <summary>
27+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
28+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
29+
/// any release. You should only use it directly in your code with extreme caution and knowing that
30+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
31+
/// </summary>
32+
Ordinates HandleOrdinates { get; }
33+
34+
/// <summary>
35+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
36+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
37+
/// any release. You should only use it directly in your code with extreme caution and knowing that
38+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
39+
/// </summary>
40+
bool IsGeographyDefault { get; }
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using Npgsql.EntityFrameworkCore.PostgreSQL.Internal;
2+
3+
namespace Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.Internal;
4+
5+
/// <summary>
6+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
7+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
8+
/// any release. You should only use it directly in your code with extreme caution and knowing that
9+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
10+
/// </summary>
11+
public class NetTopologySuiteDataSourceConfigurationPlugin(INpgsqlNetTopologySuiteSingletonOptions options)
12+
: INpgsqlDataSourceConfigurationPlugin
13+
{
14+
/// <summary>
15+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
16+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
17+
/// any release. You should only use it directly in your code with extreme caution and knowing that
18+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
19+
/// </summary>
20+
public void Configure(NpgsqlDataSourceBuilder npgsqlDataSourceBuilder)
21+
=> npgsqlDataSourceBuilder.UseNetTopologySuite(
22+
options.CoordinateSequenceFactory,
23+
options.PrecisionModel,
24+
options.HandleOrdinates,
25+
options.IsGeographyDefault);
26+
}

src/EFCore.PG.NTS/Infrastructure/Internal/NpgsqlNetTopologySuiteOptionsExtension.cs

+75-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,30 @@ public class NpgsqlNetTopologySuiteOptionsExtension : IDbContextOptionsExtension
1414
{
1515
private DbContextOptionsExtensionInfo? _info;
1616

17+
/// <summary>
18+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
19+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
20+
/// any release. You should only use it directly in your code with extreme caution and knowing that
21+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
22+
/// </summary>
23+
public virtual CoordinateSequenceFactory? CoordinateSequenceFactory { get; private set; }
24+
25+
/// <summary>
26+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
27+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
28+
/// any release. You should only use it directly in your code with extreme caution and knowing that
29+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
30+
/// </summary>
31+
public virtual PrecisionModel? PrecisionModel { get; private set; }
32+
33+
/// <summary>
34+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
35+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
36+
/// any release. You should only use it directly in your code with extreme caution and knowing that
37+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
38+
/// </summary>
39+
public virtual Ordinates HandleOrdinates { get; private set; }
40+
1741
/// <summary>
1842
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
1943
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
@@ -68,6 +92,52 @@ public virtual void ApplyServices(IServiceCollection services)
6892
public virtual DbContextOptionsExtensionInfo Info
6993
=> _info ??= new ExtensionInfo(this);
7094

95+
/// <summary>
96+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
97+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
98+
/// any release. You should only use it directly in your code with extreme caution and knowing that
99+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
100+
/// </summary>
101+
public virtual NpgsqlNetTopologySuiteOptionsExtension WithCoordinateSequenceFactory(
102+
CoordinateSequenceFactory? coordinateSequenceFactory)
103+
{
104+
var clone = Clone();
105+
106+
clone.CoordinateSequenceFactory = coordinateSequenceFactory;
107+
108+
return clone;
109+
}
110+
111+
/// <summary>
112+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
113+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
114+
/// any release. You should only use it directly in your code with extreme caution and knowing that
115+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
116+
/// </summary>
117+
public virtual NpgsqlNetTopologySuiteOptionsExtension WithPrecisionModel(PrecisionModel? precisionModel)
118+
{
119+
var clone = Clone();
120+
121+
clone.PrecisionModel = precisionModel;
122+
123+
return clone;
124+
}
125+
126+
/// <summary>
127+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
128+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
129+
/// any release. You should only use it directly in your code with extreme caution and knowing that
130+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
131+
/// </summary>
132+
public virtual NpgsqlNetTopologySuiteOptionsExtension WithHandleOrdinates(Ordinates handleOrdinates)
133+
{
134+
var clone = Clone();
135+
136+
clone.HandleOrdinates = handleOrdinates;
137+
138+
return clone;
139+
}
140+
71141
/// <summary>
72142
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
73143
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
@@ -123,7 +193,11 @@ public override int GetServiceProviderHashCode()
123193
=> Extension.IsGeographyDefault.GetHashCode();
124194

125195
public override bool ShouldUseSameServiceProvider(DbContextOptionsExtensionInfo other)
126-
=> true;
196+
=> other is ExtensionInfo otherInfo
197+
&& ReferenceEquals(Extension.CoordinateSequenceFactory, otherInfo.Extension.CoordinateSequenceFactory)
198+
&& ReferenceEquals(Extension.PrecisionModel, otherInfo.Extension.PrecisionModel)
199+
&& Extension.HandleOrdinates == otherInfo.Extension.HandleOrdinates
200+
&& Extension.IsGeographyDefault == otherInfo.Extension.IsGeographyDefault;
127201

128202
public override void PopulateDebugInfo(IDictionary<string, string> debugInfo)
129203
{

src/EFCore.PG.NTS/Internal/NpgsqlNetTopologySuiteOptions.cs src/EFCore.PG.NTS/Internal/NpgsqlNetTopologySuiteSingletonOptions.cs

+13-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,17 @@
44
namespace Npgsql.EntityFrameworkCore.PostgreSQL.Internal;
55

66
/// <inheritdoc />
7-
public class NpgsqlNetTopologySuiteOptions : INpgsqlNetTopologySuiteOptions
7+
public class NpgsqlNetTopologySuiteSingletonOptions : INpgsqlNetTopologySuiteSingletonOptions
88
{
9+
/// <inheritdoc />
10+
public virtual CoordinateSequenceFactory? CoordinateSequenceFactory { get; set; }
11+
12+
/// <inheritdoc />
13+
public virtual PrecisionModel? PrecisionModel { get; set; }
14+
15+
/// <inheritdoc />
16+
public virtual Ordinates HandleOrdinates { get; set; }
17+
918
/// <inheritdoc />
1019
public virtual bool IsGeographyDefault { get; set; }
1120

@@ -15,6 +24,9 @@ public virtual void Initialize(IDbContextOptions options)
1524
var npgsqlNtsOptions = options.FindExtension<NpgsqlNetTopologySuiteOptionsExtension>()
1625
?? new NpgsqlNetTopologySuiteOptionsExtension();
1726

27+
CoordinateSequenceFactory = npgsqlNtsOptions.CoordinateSequenceFactory;
28+
PrecisionModel = npgsqlNtsOptions.PrecisionModel;
29+
HandleOrdinates = npgsqlNtsOptions.HandleOrdinates;
1830
IsGeographyDefault = npgsqlNtsOptions.IsGeographyDefault;
1931
}
2032

src/EFCore.PG.NTS/Storage/Internal/NpgsqlNetTopologySuiteTypeMappingSourcePlugin.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public class NpgsqlNetTopologySuiteTypeMappingSourcePlugin : IRelationalTypeMapp
1515
{
1616
// Note: we reference the options rather than copying IsGeographyDefault out, because that field is initialized
1717
// rather late by SingletonOptionsInitializer
18-
private readonly INpgsqlNetTopologySuiteOptions _options;
18+
private readonly INpgsqlNetTopologySuiteSingletonOptions _options;
1919

2020
private static bool TryGetClrType(string subtypeName, [NotNullWhen(true)] out Type? clrType)
2121
{
@@ -41,7 +41,7 @@ private static bool TryGetClrType(string subtypeName, [NotNullWhen(true)] out Ty
4141
/// any release. You should only use it directly in your code with extreme caution and knowing that
4242
/// doing so can result in application failures when updating to a new Entity Framework Core release.
4343
/// </summary>
44-
public NpgsqlNetTopologySuiteTypeMappingSourcePlugin(INpgsqlNetTopologySuiteOptions options)
44+
public NpgsqlNetTopologySuiteTypeMappingSourcePlugin(INpgsqlNetTopologySuiteSingletonOptions options)
4545
{
4646
_options = Check.NotNull(options, nameof(options));
4747
}

src/EFCore.PG.NodaTime/Extensions/NpgsqlNodaTimeDbContextOptionsBuilderExtensions.cs

-5
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,6 @@ public static NpgsqlDbContextOptionsBuilder UseNodaTime(
1818
{
1919
Check.NotNull(optionsBuilder, nameof(optionsBuilder));
2020

21-
// TODO: Global-only setup at the ADO.NET level for now, optionally allow per-connection?
22-
#pragma warning disable CS0618 // NpgsqlConnection.GlobalTypeMapper is obsolete
23-
NpgsqlConnection.GlobalTypeMapper.UseNodaTime();
24-
#pragma warning restore CS0618
25-
2621
var coreOptionsBuilder = ((IRelationalDbContextOptionsBuilderInfrastructure)optionsBuilder).OptionsBuilder;
2722

2823
var extension = coreOptionsBuilder.Options.FindExtension<NpgsqlNodaTimeOptionsExtension>()

0 commit comments

Comments
 (0)