Skip to content

Commit

Permalink
Major work around DbDataSource management, enum handling and plugins
Browse files Browse the repository at this point in the history
Fixes #2891
Fixes #3063
Fixes #1026

Co-authored-by: Nino Floris <mail@ninofloris.com>
  • Loading branch information
roji and NinoFloris committed May 13, 2024
1 parent f69fc1d commit d4ae264
Show file tree
Hide file tree
Showing 58 changed files with 3,311 additions and 355 deletions.
15 changes: 0 additions & 15 deletions EFCore.PG.sln
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore.PG.Tests", "test\EFC
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore.PG.FunctionalTests", "test\EFCore.PG.FunctionalTests\EFCore.PG.FunctionalTests.csproj", "{05A7D0B7-4AE1-4BC8-A1BE-2389F1593B2D}"
EndProject
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}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore.PG.NodaTime", "src\EFCore.PG.NodaTime\EFCore.PG.NodaTime.csproj", "{77F0608F-6D0C-481C-9108-D5176E2EAD69}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFCore.PG.NTS", "src\EFCore.PG.NTS\EFCore.PG.NTS.csproj", "{D7106D61-C7CA-4005-B31F-43281BB397AD}"
Expand Down Expand Up @@ -70,18 +68,6 @@ Global
{05A7D0B7-4AE1-4BC8-A1BE-2389F1593B2D}.Release|Any CPU.Build.0 = Release|Any CPU
{05A7D0B7-4AE1-4BC8-A1BE-2389F1593B2D}.Release|x64.ActiveCfg = Release|Any CPU
{05A7D0B7-4AE1-4BC8-A1BE-2389F1593B2D}.Release|x86.ActiveCfg = Release|Any CPU
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Debug|x64.ActiveCfg = Debug|Any CPU
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Debug|x64.Build.0 = Debug|Any CPU
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Debug|x86.ActiveCfg = Debug|Any CPU
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Debug|x86.Build.0 = Debug|Any CPU
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Release|Any CPU.Build.0 = Release|Any CPU
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Release|x64.ActiveCfg = Release|Any CPU
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Release|x64.Build.0 = Release|Any CPU
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Release|x86.ActiveCfg = Release|Any CPU
{B78A7825-BE72-4509-B0AD-01EEC67A9624}.Release|x86.Build.0 = Release|Any CPU
{77F0608F-6D0C-481C-9108-D5176E2EAD69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{77F0608F-6D0C-481C-9108-D5176E2EAD69}.Debug|Any CPU.Build.0 = Debug|Any CPU
{77F0608F-6D0C-481C-9108-D5176E2EAD69}.Debug|x64.ActiveCfg = Debug|Any CPU
Expand Down Expand Up @@ -114,7 +100,6 @@ Global
{FADDA2D1-03B4-4DEF-8D24-DD1CA4E81F4A} = {8537E50E-CF7F-49CB-B4EF-3E2A1B11F050}
{E1D99AD4-D88B-42BA-86DF-90B98B2E9A01} = {ED612DB1-AB32-4603-95E7-891BACA71C39}
{05A7D0B7-4AE1-4BC8-A1BE-2389F1593B2D} = {ED612DB1-AB32-4603-95E7-891BACA71C39}
{B78A7825-BE72-4509-B0AD-01EEC67A9624} = {ED612DB1-AB32-4603-95E7-891BACA71C39}
{77F0608F-6D0C-481C-9108-D5176E2EAD69} = {8537E50E-CF7F-49CB-B4EF-3E2A1B11F050}
{D7106D61-C7CA-4005-B31F-43281BB397AD} = {8537E50E-CF7F-49CB-B4EF-3E2A1B11F050}
{26203F54-A3C1-43AD-A101-8F589D2D67AD} = {4A5A60DD-41B6-40BF-B677-227A921ECCC8}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ public virtual void ConfigureDesignTimeServices(IServiceCollection serviceCollec
=> serviceCollection
.AddSingleton<IRelationalTypeMappingSourcePlugin, NpgsqlNetTopologySuiteTypeMappingSourcePlugin>()
.AddSingleton<IProviderCodeGeneratorPlugin, NpgsqlNetTopologySuiteCodeGeneratorPlugin>()
.TryAddSingleton<INpgsqlNetTopologySuiteOptions, NpgsqlNetTopologySuiteOptions>();
.TryAddSingleton<INpgsqlNetTopologySuiteSingletonOptions, NpgsqlNetTopologySuiteSingletonOptions>();
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,26 @@ public static NpgsqlDbContextOptionsBuilder UseNetTopologySuite(
Ordinates handleOrdinates = Ordinates.None,
bool geographyAsDefault = false)
{
Check.NotNull(optionsBuilder, nameof(optionsBuilder));

// TODO: Global-only setup at the ADO.NET level for now, optionally allow per-connection?
#pragma warning disable CS0618 // NpgsqlConnection.GlobalTypeMapper is obsolete
NpgsqlConnection.GlobalTypeMapper.UseNetTopologySuite(
coordinateSequenceFactory, precisionModel, handleOrdinates, geographyAsDefault);
#pragma warning restore CS0618

var coreOptionsBuilder = ((IRelationalDbContextOptionsBuilderInfrastructure)optionsBuilder).OptionsBuilder;

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

if (coordinateSequenceFactory is not null)
{
extension = extension.WithCoordinateSequenceFactory(coordinateSequenceFactory);
}

if (precisionModel is not null)
{
extension = extension.WithPrecisionModel(precisionModel);
}

if (handleOrdinates is not Ordinates.None)
{
extension = extension.WithHandleOrdinates(handleOrdinates);
}

if (geographyAsDefault)
{
extension = extension.WithGeographyDefault();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure;
using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.Internal;
using Npgsql.EntityFrameworkCore.PostgreSQL.Internal;
using Npgsql.EntityFrameworkCore.PostgreSQL.Query.ExpressionTranslators.Internal;
Expand All @@ -21,15 +22,16 @@ public static IServiceCollection AddEntityFrameworkNpgsqlNetTopologySuite(
{
Check.NotNull(serviceCollection, nameof(serviceCollection));

new EntityFrameworkRelationalServicesBuilder(serviceCollection)
.TryAdd<ISingletonOptions, INpgsqlNetTopologySuiteOptions>(p => p.GetRequiredService<INpgsqlNetTopologySuiteOptions>())
new EntityFrameworkNpgsqlServicesBuilder(serviceCollection)
.TryAdd<INpgsqlDataSourceConfigurationPlugin, NetTopologySuiteDataSourceConfigurationPlugin>()
.TryAdd<ISingletonOptions, INpgsqlNetTopologySuiteSingletonOptions>(p => p.GetRequiredService<INpgsqlNetTopologySuiteSingletonOptions>())
.TryAdd<IRelationalTypeMappingSourcePlugin, NpgsqlNetTopologySuiteTypeMappingSourcePlugin>()
.TryAdd<IMethodCallTranslatorPlugin, NpgsqlNetTopologySuiteMethodCallTranslatorPlugin>()
.TryAdd<IAggregateMethodCallTranslatorPlugin, NpgsqlNetTopologySuiteAggregateMethodCallTranslatorPlugin>()
.TryAdd<IMemberTranslatorPlugin, NpgsqlNetTopologySuiteMemberTranslatorPlugin>()
.TryAdd<IConventionSetPlugin, NpgsqlNetTopologySuiteConventionSetPlugin>()
.TryAddProviderSpecificServices(
x => x.TryAddSingleton<INpgsqlNetTopologySuiteOptions, NpgsqlNetTopologySuiteOptions>());
x => x.TryAddSingleton<INpgsqlNetTopologySuiteSingletonOptions, NpgsqlNetTopologySuiteSingletonOptions>());

return serviceCollection;
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// ReSharper disable once CheckNamespace

namespace Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.Internal;

/// <summary>
/// Represents options for Npgsql NetTopologySuite that can only be set at the <see cref="System.IServiceProvider" /> singleton level.
/// </summary>
public interface INpgsqlNetTopologySuiteSingletonOptions : ISingletonOptions
{
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
CoordinateSequenceFactory? CoordinateSequenceFactory { get; }

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
PrecisionModel? PrecisionModel { get; }

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
Ordinates HandleOrdinates { get; }

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
bool IsGeographyDefault { get; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Npgsql.EntityFrameworkCore.PostgreSQL.Internal;

namespace Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.Internal;

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public class NetTopologySuiteDataSourceConfigurationPlugin(INpgsqlNetTopologySuiteSingletonOptions options)
: INpgsqlDataSourceConfigurationPlugin
{
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public void Configure(NpgsqlDataSourceBuilder npgsqlDataSourceBuilder)
=> npgsqlDataSourceBuilder.UseNetTopologySuite(
options.CoordinateSequenceFactory,
options.PrecisionModel,
options.HandleOrdinates,
options.IsGeographyDefault);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,30 @@ public class NpgsqlNetTopologySuiteOptionsExtension : IDbContextOptionsExtension
{
private DbContextOptionsExtensionInfo? _info;

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual CoordinateSequenceFactory? CoordinateSequenceFactory { get; private set; }

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual PrecisionModel? PrecisionModel { get; private set; }

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual Ordinates HandleOrdinates { get; private set; }

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
Expand Down Expand Up @@ -68,6 +92,52 @@ public virtual void ApplyServices(IServiceCollection services)
public virtual DbContextOptionsExtensionInfo Info
=> _info ??= new ExtensionInfo(this);

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual NpgsqlNetTopologySuiteOptionsExtension WithCoordinateSequenceFactory(
CoordinateSequenceFactory? coordinateSequenceFactory)
{
var clone = Clone();

clone.CoordinateSequenceFactory = coordinateSequenceFactory;

return clone;
}

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual NpgsqlNetTopologySuiteOptionsExtension WithPrecisionModel(PrecisionModel? precisionModel)
{
var clone = Clone();

clone.PrecisionModel = precisionModel;

return clone;
}

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual NpgsqlNetTopologySuiteOptionsExtension WithHandleOrdinates(Ordinates handleOrdinates)
{
var clone = Clone();

clone.HandleOrdinates = handleOrdinates;

return clone;
}

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
Expand Down Expand Up @@ -123,7 +193,11 @@ public override int GetServiceProviderHashCode()
=> Extension.IsGeographyDefault.GetHashCode();

public override bool ShouldUseSameServiceProvider(DbContextOptionsExtensionInfo other)
=> true;
=> other is ExtensionInfo otherInfo
&& ReferenceEquals(Extension.CoordinateSequenceFactory, otherInfo.Extension.CoordinateSequenceFactory)
&& ReferenceEquals(Extension.PrecisionModel, otherInfo.Extension.PrecisionModel)
&& Extension.HandleOrdinates == otherInfo.Extension.HandleOrdinates
&& Extension.IsGeographyDefault == otherInfo.Extension.IsGeographyDefault;

public override void PopulateDebugInfo(IDictionary<string, string> debugInfo)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,17 @@
namespace Npgsql.EntityFrameworkCore.PostgreSQL.Internal;

/// <inheritdoc />
public class NpgsqlNetTopologySuiteOptions : INpgsqlNetTopologySuiteOptions
public class NpgsqlNetTopologySuiteSingletonOptions : INpgsqlNetTopologySuiteSingletonOptions
{
/// <inheritdoc />
public virtual CoordinateSequenceFactory? CoordinateSequenceFactory { get; set; }

/// <inheritdoc />
public virtual PrecisionModel? PrecisionModel { get; set; }

/// <inheritdoc />
public virtual Ordinates HandleOrdinates { get; set; }

/// <inheritdoc />
public virtual bool IsGeographyDefault { get; set; }

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

CoordinateSequenceFactory = npgsqlNtsOptions.CoordinateSequenceFactory;
PrecisionModel = npgsqlNtsOptions.PrecisionModel;
HandleOrdinates = npgsqlNtsOptions.HandleOrdinates;
IsGeographyDefault = npgsqlNtsOptions.IsGeographyDefault;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class NpgsqlNetTopologySuiteTypeMappingSourcePlugin : IRelationalTypeMapp
{
// Note: we reference the options rather than copying IsGeographyDefault out, because that field is initialized
// rather late by SingletonOptionsInitializer
private readonly INpgsqlNetTopologySuiteOptions _options;
private readonly INpgsqlNetTopologySuiteSingletonOptions _options;

private static bool TryGetClrType(string subtypeName, [NotNullWhen(true)] out Type? clrType)
{
Expand All @@ -41,7 +41,7 @@ private static bool TryGetClrType(string subtypeName, [NotNullWhen(true)] out Ty
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public NpgsqlNetTopologySuiteTypeMappingSourcePlugin(INpgsqlNetTopologySuiteOptions options)
public NpgsqlNetTopologySuiteTypeMappingSourcePlugin(INpgsqlNetTopologySuiteSingletonOptions options)
{
_options = Check.NotNull(options, nameof(options));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@ public static NpgsqlDbContextOptionsBuilder UseNodaTime(
{
Check.NotNull(optionsBuilder, nameof(optionsBuilder));

// TODO: Global-only setup at the ADO.NET level for now, optionally allow per-connection?
#pragma warning disable CS0618 // NpgsqlConnection.GlobalTypeMapper is obsolete
NpgsqlConnection.GlobalTypeMapper.UseNodaTime();
#pragma warning restore CS0618

var coreOptionsBuilder = ((IRelationalDbContextOptionsBuilderInfrastructure)optionsBuilder).OptionsBuilder;

var extension = coreOptionsBuilder.Options.FindExtension<NpgsqlNodaTimeOptionsExtension>()
Expand Down
Loading

0 comments on commit d4ae264

Please sign in to comment.