using System;
using System.Diagnostics.CodeAnalysis;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Npgsql.Internal;
using Npgsql.Internal.ResolverFactories;
using Npgsql.NameTranslation;
using Npgsql.TypeMapping;
using NpgsqlTypes;
namespace Npgsql;
///
/// Provides a simple API for configuring and creating an , from which database connections can be obtained.
///
public sealed class NpgsqlDataSourceBuilder : INpgsqlTypeMapper
{
static UnsupportedTypeInfoResolver UnsupportedTypeInfoResolver { get; } = new();
readonly NpgsqlSlimDataSourceBuilder _internalBuilder;
///
/// A diagnostics name used by Npgsql when generating tracing, logging and metrics.
///
public string? Name
{
get => _internalBuilder.Name;
set => _internalBuilder.Name = value;
}
///
public INpgsqlNameTranslator DefaultNameTranslator
{
get => _internalBuilder.DefaultNameTranslator;
set => _internalBuilder.DefaultNameTranslator = value;
}
///
/// A connection string builder that can be used to configure the connection string on the builder.
///
public NpgsqlConnectionStringBuilder ConnectionStringBuilder => _internalBuilder.ConnectionStringBuilder;
///
/// Returns the connection string, as currently configured on the builder.
///
public string ConnectionString => _internalBuilder.ConnectionString;
internal static void ResetGlobalMappings(bool overwrite)
=> GlobalTypeMapper.Instance.AddGlobalTypeMappingResolvers([
overwrite ? new AdoTypeInfoResolverFactory() : AdoTypeInfoResolverFactory.Instance,
new ExtraConversionResolverFactory(),
new JsonTypeInfoResolverFactory(),
new RecordTypeInfoResolverFactory(),
new FullTextSearchTypeInfoResolverFactory(),
new NetworkTypeInfoResolverFactory(),
new GeometricTypeInfoResolverFactory(),
new LTreeTypeInfoResolverFactory(),
new CubeTypeInfoResolverFactory()
], static () =>
{
var builder = new PgTypeInfoResolverChainBuilder();
builder.EnableRanges();
builder.EnableMultiranges();
builder.EnableArrays();
return builder;
}, overwrite);
static NpgsqlDataSourceBuilder()
=> ResetGlobalMappings(overwrite: false);
///
/// Constructs a new , optionally starting out from the given .
///
public NpgsqlDataSourceBuilder(string? connectionString = null)
{
_internalBuilder = new(new NpgsqlConnectionStringBuilder(connectionString));
_internalBuilder.ConfigureDefaultFactories = static instance =>
{
instance.AppendDefaultFactories();
instance.AppendResolverFactory(new ExtraConversionResolverFactory());
instance.AppendResolverFactory(() => new JsonTypeInfoResolverFactory(instance.JsonSerializerOptions));
instance.AppendResolverFactory(new RecordTypeInfoResolverFactory());
instance.AppendResolverFactory(new FullTextSearchTypeInfoResolverFactory());
instance.AppendResolverFactory(new NetworkTypeInfoResolverFactory());
instance.AppendResolverFactory(new GeometricTypeInfoResolverFactory());
instance.AppendResolverFactory(new LTreeTypeInfoResolverFactory());
instance.AppendResolverFactory(new CubeTypeInfoResolverFactory());
};
_internalBuilder.ConfigureResolverChain = static chain => chain.Add(UnsupportedTypeInfoResolver);
_internalBuilder.EnableTransportSecurity();
_internalBuilder.EnableIntegratedSecurity();
_internalBuilder.EnableRanges();
_internalBuilder.EnableMultiranges();
_internalBuilder.EnableArrays();
}
///
/// Sets the that will be used for logging.
///
/// The logger factory to be used.
/// The same builder instance so that multiple calls can be chained.
public NpgsqlDataSourceBuilder UseLoggerFactory(ILoggerFactory? loggerFactory)
{
_internalBuilder.UseLoggerFactory(loggerFactory);
return this;
}
///
/// Enables parameters to be included in logging. This includes potentially sensitive information from data sent to PostgreSQL.
/// You should only enable this flag in development, or if you have the appropriate security measures in place based on the
/// sensitivity of this data.
///
/// If , then sensitive data is logged.
/// The same builder instance so that multiple calls can be chained.
public NpgsqlDataSourceBuilder EnableParameterLogging(bool parameterLoggingEnabled = true)
{
_internalBuilder.EnableParameterLogging(parameterLoggingEnabled);
return this;
}
///
/// Configures type loading options for the DataSource.
///
public NpgsqlDataSourceBuilder ConfigureTypeLoading(Action configureAction)
{
_internalBuilder.ConfigureTypeLoading(configureAction);
return this;
}
///
/// Configures OpenTelemetry tracing options.
///
/// The same builder instance so that multiple calls can be chained.
public NpgsqlDataSourceBuilder ConfigureTracing(Action configureAction)
{
_internalBuilder.ConfigureTracing(configureAction);
return this;
}
///
/// Configures the JSON serializer options used when reading and writing all System.Text.Json data.
///
/// Options to customize JSON serialization and deserialization.
/// The same builder instance so that multiple calls can be chained.
public NpgsqlDataSourceBuilder ConfigureJsonOptions(JsonSerializerOptions serializerOptions)
{
_internalBuilder.ConfigureJsonOptions(serializerOptions);
return this;
}
///
/// Sets up dynamic System.Text.Json mappings. This allows mapping arbitrary .NET types to PostgreSQL json and jsonb
/// types, as well as and its derived types.
///
///
/// A list of CLR types to map to PostgreSQL jsonb (no need to specify ).
///
///
/// A list of CLR types to map to PostgreSQL json (no need to specify ).
///
///
/// Due to the dynamic nature of these mappings, they are not compatible with NativeAOT or trimming.
///
[RequiresUnreferencedCode("Json serializer may perform reflection on trimmed types.")]
[RequiresDynamicCode("Serializing arbitrary types to json can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")]
public NpgsqlDataSourceBuilder EnableDynamicJson(Type[]? jsonbClrTypes = null, Type[]? jsonClrTypes = null)
{
_internalBuilder.EnableDynamicJson(jsonbClrTypes, jsonClrTypes);
return this;
}
///
/// Sets up mappings for the PostgreSQL record type as a .NET or .
///
/// The same builder instance so that multiple calls can be chained.
[RequiresUnreferencedCode("The mapping of PostgreSQL records as .NET tuples requires reflection usage which is incompatible with trimming.")]
[RequiresDynamicCode("The mapping of PostgreSQL records as .NET tuples requires dynamic code usage which is incompatible with NativeAOT.")]
public NpgsqlDataSourceBuilder EnableRecordsAsTuples()
{
AddTypeInfoResolverFactory(new TupledRecordTypeInfoResolverFactory());
return this;
}
///
/// Sets up mappings allowing the use of unmapped enum, range and multirange types.
///
/// The same builder instance so that multiple calls can be chained.
[RequiresUnreferencedCode("The use of unmapped enums, ranges or multiranges requires reflection usage which is incompatible with trimming.")]
[RequiresDynamicCode("The use of unmapped enums, ranges or multiranges requires dynamic code usage which is incompatible with NativeAOT.")]
public NpgsqlDataSourceBuilder EnableUnmappedTypes()
{
AddTypeInfoResolverFactory(new UnmappedTypeInfoResolverFactory());
return this;
}
#region Authentication
///
/// When using SSL/TLS, this is a callback that allows customizing how the PostgreSQL-provided certificate is verified. This is an
/// advanced API, consider using or instead.
///
/// The callback containing custom callback verification logic.
///
///
/// Cannot be used in conjunction with , or
/// .
///
///
/// See .
///
///
/// The same builder instance so that multiple calls can be chained.
[Obsolete("Use UseSslClientAuthenticationOptionsCallback")]
public NpgsqlDataSourceBuilder UseUserCertificateValidationCallback(RemoteCertificateValidationCallback userCertificateValidationCallback)
{
_internalBuilder.UseUserCertificateValidationCallback(userCertificateValidationCallback);
return this;
}
///
/// Specifies an SSL/TLS certificate which Npgsql will send to PostgreSQL for certificate-based authentication.
///
/// The client certificate to be sent to PostgreSQL when opening a connection.
/// The same builder instance so that multiple calls can be chained.
[Obsolete("Use UseSslClientAuthenticationOptionsCallback")]
public NpgsqlDataSourceBuilder UseClientCertificate(X509Certificate? clientCertificate)
{
_internalBuilder.UseClientCertificate(clientCertificate);
return this;
}
///
/// Specifies a collection of SSL/TLS certificates which Npgsql will send to PostgreSQL for certificate-based authentication.
///
/// The client certificate collection to be sent to PostgreSQL when opening a connection.
/// The same builder instance so that multiple calls can be chained.
[Obsolete("Use UseSslClientAuthenticationOptionsCallback")]
public NpgsqlDataSourceBuilder UseClientCertificates(X509CertificateCollection? clientCertificates)
{
_internalBuilder.UseClientCertificates(clientCertificates);
return this;
}
///
/// When using SSL/TLS, this is a callback that allows customizing SslStream's authentication options.
///
/// The callback to customize SslStream's authentication options.
///
///
/// See .
///
///
/// The same builder instance so that multiple calls can be chained.
public NpgsqlDataSourceBuilder UseSslClientAuthenticationOptionsCallback(Action? sslClientAuthenticationOptionsCallback)
{
_internalBuilder.UseSslClientAuthenticationOptionsCallback(sslClientAuthenticationOptionsCallback);
return this;
}
///
/// Specifies a callback to modify the collection of SSL/TLS client certificates which Npgsql will send to PostgreSQL for
/// certificate-based authentication. This is an advanced API, consider using or
/// instead.
///
/// The callback to modify the client certificate collection.
///
///
/// The callback is invoked every time a physical connection is opened, and is therefore suitable for rotating short-lived client
/// certificates. Simply make sure the certificate collection argument has the up-to-date certificate(s).
///
///
/// The callback's collection argument already includes any client certificates specified via the connection string or environment
/// variables.
///
///
/// The same builder instance so that multiple calls can be chained.
[Obsolete("Use UseSslClientAuthenticationOptionsCallback")]
public NpgsqlDataSourceBuilder UseClientCertificatesCallback(Action? clientCertificatesCallback)
{
_internalBuilder.UseClientCertificatesCallback(clientCertificatesCallback);
return this;
}
///
/// Sets the that will be used validate SSL certificate, received from the server.
///
/// The CA certificate.
/// The same builder instance so that multiple calls can be chained.
public NpgsqlDataSourceBuilder UseRootCertificate(X509Certificate2? rootCertificate)
{
_internalBuilder.UseRootCertificate(rootCertificate);
return this;
}
///
/// Sets the that will be used validate SSL certificate, received from the server.
///
/// The CA certificates.
/// The same builder instance so that multiple calls can be chained.
public NpgsqlDataSourceBuilder UseRootCertificates(X509Certificate2Collection? rootCertificates)
{
_internalBuilder.UseRootCertificates(rootCertificates);
return this;
}
///
/// Specifies a callback that will be used to validate SSL certificate, received from the server.
///
/// The callback to get CA certificate.
/// The same builder instance so that multiple calls can be chained.
///
/// This overload, which accepts a callback, is suitable for scenarios where the certificate rotates
/// and might change during the lifetime of the application.
/// When that's not the case, use the overload which directly accepts the certificate.
///
public NpgsqlDataSourceBuilder UseRootCertificateCallback(Func? rootCertificateCallback)
{
_internalBuilder.UseRootCertificateCallback(rootCertificateCallback);
return this;
}
///
/// Specifies a callback that will be used to validate SSL certificate, received from the server.
///
/// The callback to get CA certificates.
/// The same builder instance so that multiple calls can be chained.
///
/// This overload, which accepts a callback, is suitable for scenarios where the certificate rotates
/// and might change during the lifetime of the application.
/// When that's not the case, use the overload which directly accepts the certificate.
///
/// The same builder instance so that multiple calls can be chained.
public NpgsqlDataSourceBuilder UseRootCertificatesCallback(Func? rootCertificateCallback)
{
_internalBuilder.UseRootCertificatesCallback(rootCertificateCallback);
return this;
}
///
/// Configures a periodic password provider, which is automatically called by the data source at some regular interval. This is the
/// recommended way to fetch a rotating access token.
///
/// A callback which returns the password to be sent to PostgreSQL.
/// How long to cache the password before re-invoking the callback.
///
/// If a password refresh attempt fails, it will be re-attempted with this interval.
/// This should typically be much lower than .
///
/// The same builder instance so that multiple calls can be chained.
///
///
/// The provided callback is invoked in a timer, and not when opening connections. It therefore doesn't affect opening time.
///
///
/// The provided cancellation token is only triggered when the entire data source is disposed. If you'd like to apply a timeout to the
/// token fetching, do so within the provided callback.
///
///
public NpgsqlDataSourceBuilder UsePeriodicPasswordProvider(
Func>? passwordProvider,
TimeSpan successRefreshInterval,
TimeSpan failureRefreshInterval)
{
_internalBuilder.UsePeriodicPasswordProvider(passwordProvider, successRefreshInterval, failureRefreshInterval);
return this;
}
///
/// Configures a password provider, which is called by the data source when opening connections.
///
///
/// A callback that may be invoked during which returns the password to be sent to PostgreSQL.
///
///
/// A callback that may be invoked during which returns the password to be sent to PostgreSQL.
///
/// The same builder instance so that multiple calls can be chained.
///
///
/// The provided callback is invoked when opening connections. Therefore its important the callback internally depends on cached
/// data or returns quickly otherwise. Any unnecessary delay will affect connection opening time.
///
///
public NpgsqlDataSourceBuilder UsePasswordProvider(
Func? passwordProvider,
Func>? passwordProviderAsync)
{
_internalBuilder.UsePasswordProvider(passwordProvider, passwordProviderAsync);
return this;
}
///
/// When using Kerberos, this is a callback that allows customizing default settings for Kerberos authentication.
///
/// The callback containing logic to customize Kerberos authentication settings.
///
///
/// See .
///
///
/// The same builder instance so that multiple calls can be chained.
public NpgsqlDataSourceBuilder UseNegotiateOptionsCallback(Action? negotiateOptionsCallback)
{
_internalBuilder.UseNegotiateOptionsCallback(negotiateOptionsCallback);
return this;
}
#endregion Authentication
#region Type mapping
///
void INpgsqlTypeMapper.AddDbTypeResolverFactory(DbTypeResolverFactory factory)
=> ((INpgsqlTypeMapper)_internalBuilder).AddDbTypeResolverFactory(factory);
///
[Experimental(NpgsqlDiagnostics.ConvertersExperimental)]
public void AddTypeInfoResolverFactory(PgTypeInfoResolverFactory factory)
=> _internalBuilder.AddTypeInfoResolverFactory(factory);
///
void INpgsqlTypeMapper.Reset() => ((INpgsqlTypeMapper)_internalBuilder).Reset();
///
/// Maps a CLR enum to a PostgreSQL enum type.
///
///
/// CLR enum labels are mapped by name to PostgreSQL enum labels.
/// The translation strategy can be controlled by the parameter,
/// which defaults to .
/// You can also use the on your enum fields to manually specify a PostgreSQL enum label.
/// If there is a discrepancy between the .NET and database labels while an enum is read or written,
/// an exception will be raised.
///
///
/// A PostgreSQL type name for the corresponding enum type in the database.
/// If null, the name translator given in will be used.
///
///
/// A component which will be used to translate CLR names (e.g. SomeClass) into database names (e.g. some_class).
/// Defaults to .
///
/// The .NET enum type to be mapped
public NpgsqlDataSourceBuilder MapEnum<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] TEnum>(string? pgName = null, INpgsqlNameTranslator? nameTranslator = null)
where TEnum : struct, Enum
{
_internalBuilder.MapEnum(pgName, nameTranslator);
return this;
}
///
public bool UnmapEnum<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] TEnum>(string? pgName = null, INpgsqlNameTranslator? nameTranslator = null)
where TEnum : struct, Enum
=> _internalBuilder.UnmapEnum(pgName, nameTranslator);
///
/// Maps a CLR enum to a PostgreSQL enum type.
///
///
/// CLR enum labels are mapped by name to PostgreSQL enum labels.
/// The translation strategy can be controlled by the parameter,
/// which defaults to .
/// You can also use the on your enum fields to manually specify a PostgreSQL enum label.
/// If there is a discrepancy between the .NET and database labels while an enum is read or written,
/// an exception will be raised.
///
/// The .NET enum type to be mapped
///
/// A PostgreSQL type name for the corresponding enum type in the database.
/// If null, the name translator given in will be used.
///
///
/// A component which will be used to translate CLR names (e.g. SomeClass) into database names (e.g. some_class).
/// Defaults to .
///
[RequiresDynamicCode("Calling MapEnum with a Type can require creating new generic types or methods. This may not work when AOT compiling.")]
public NpgsqlDataSourceBuilder MapEnum([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
Type clrType, string? pgName = null, INpgsqlNameTranslator? nameTranslator = null)
{
_internalBuilder.MapEnum(clrType, pgName, nameTranslator);
return this;
}
///
public bool UnmapEnum([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
Type clrType, string? pgName = null, INpgsqlNameTranslator? nameTranslator = null)
=> _internalBuilder.UnmapEnum(clrType, pgName, nameTranslator);
///
/// Maps a CLR type to a PostgreSQL composite type.
///
///
/// CLR fields and properties by string to PostgreSQL names.
/// The translation strategy can be controlled by the parameter,
/// which defaults to .
/// You can also use the on your members to manually specify a PostgreSQL name.
/// If there is a discrepancy between the .NET type and database type while a composite is read or written,
/// an exception will be raised.
///
///
/// A PostgreSQL type name for the corresponding composite type in the database.
/// If null, the name translator given in will be used.
///
///
/// A component which will be used to translate CLR names (e.g. SomeClass) into database names (e.g. some_class).
/// Defaults to .
///
/// The .NET type to be mapped
[RequiresDynamicCode("Mapping composite types involves serializing arbitrary types which can require creating new generic types or methods. This is currently unsupported with NativeAOT, vote on issue #5303 if this is important to you.")]
public NpgsqlDataSourceBuilder MapComposite<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields)] T>(
string? pgName = null, INpgsqlNameTranslator? nameTranslator = null)
{
_internalBuilder.MapComposite(typeof(T), pgName, nameTranslator);
return this;
}
///
[RequiresDynamicCode("Mapping composite types involves serializing arbitrary types which can require creating new generic types or methods. This is currently unsupported with NativeAOT, vote on issue #5303 if this is important to you.")]
public bool UnmapComposite<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields)] T>(
string? pgName = null, INpgsqlNameTranslator? nameTranslator = null)
=> _internalBuilder.UnmapComposite(typeof(T), pgName, nameTranslator);
///
/// Maps a CLR type to a composite type.
///
///
/// Maps CLR fields and properties by string to PostgreSQL names.
/// The translation strategy can be controlled by the parameter,
/// which defaults to .
/// If there is a discrepancy between the .NET type and database type while a composite is read or written,
/// an exception will be raised.
///
/// The .NET type to be mapped.
///
/// A PostgreSQL type name for the corresponding composite type in the database.
/// If null, the name translator given in will be used.
///
///
/// A component which will be used to translate CLR names (e.g. SomeClass) into database names (e.g. some_class).
/// Defaults to .
///
[RequiresDynamicCode("Mapping composite types involves serializing arbitrary types which can require creating new generic types or methods. This is currently unsupported with NativeAOT, vote on issue #5303 if this is important to you.")]
public NpgsqlDataSourceBuilder MapComposite([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields)]
Type clrType, string? pgName = null, INpgsqlNameTranslator? nameTranslator = null)
{
_internalBuilder.MapComposite(clrType, pgName, nameTranslator);
return this;
}
///
[RequiresDynamicCode("Mapping composite types involves serializing arbitrary types which can require creating new generic types or methods. This is currently unsupported with NativeAOT, vote on issue #5303 if this is important to you.")]
public bool UnmapComposite([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields)]
Type clrType, string? pgName = null, INpgsqlNameTranslator? nameTranslator = null)
=> _internalBuilder.UnmapComposite(clrType, pgName, nameTranslator);
#endregion Type mapping
///
/// Register a connection initializer, which allows executing arbitrary commands when a physical database connection is first opened.
///
///
/// A synchronous connection initialization lambda, which will be called from when a new physical
/// connection is opened.
///
///
/// An asynchronous connection initialization lambda, which will be called from
/// when a new physical connection is opened.
///
///
/// If an initializer is registered, both sync and async versions must be provided. If you do not use sync APIs in your code, simply
/// throw , which would also catch accidental cases of sync opening.
///
///
/// Take care that the setting you apply in the initializer does not get reverted when the connection is returned to the pool, since
/// Npgsql sends DISCARD ALL by default. The option can be used to
/// turn this off.
///
/// The same builder instance so that multiple calls can be chained.
public NpgsqlDataSourceBuilder UsePhysicalConnectionInitializer(
Action? connectionInitializer,
Func? connectionInitializerAsync)
{
_internalBuilder.UsePhysicalConnectionInitializer(connectionInitializer, connectionInitializerAsync);
return this;
}
///
/// Builds and returns an which is ready for use.
///
public NpgsqlDataSource Build()
=> _internalBuilder.Build();
///
/// Builds and returns a which is ready for use for load-balancing and failover scenarios.
///
public NpgsqlMultiHostDataSource BuildMultiHost()
=> _internalBuilder.BuildMultiHost();
// Used in testing.
internal (NpgsqlConnectionStringBuilder, NpgsqlDataSourceConfiguration) PrepareConfiguration()
=> _internalBuilder.PrepareConfiguration();
INpgsqlTypeMapper INpgsqlTypeMapper.ConfigureJsonOptions(JsonSerializerOptions serializerOptions)
=> ConfigureJsonOptions(serializerOptions);
[RequiresUnreferencedCode("Json serializer may perform reflection on trimmed types.")]
[RequiresDynamicCode(
"Serializing arbitrary types to json can require creating new generic types or methods, which requires creating code at runtime. This may not work when AOT compiling.")]
INpgsqlTypeMapper INpgsqlTypeMapper.EnableDynamicJson(Type[]? jsonbClrTypes, Type[]? jsonClrTypes)
=> EnableDynamicJson(jsonbClrTypes, jsonClrTypes);
[RequiresUnreferencedCode(
"The mapping of PostgreSQL records as .NET tuples requires reflection usage which is incompatible with trimming.")]
[RequiresDynamicCode(
"The mapping of PostgreSQL records as .NET tuples requires dynamic code usage which is incompatible with NativeAOT.")]
INpgsqlTypeMapper INpgsqlTypeMapper.EnableRecordsAsTuples()
=> EnableRecordsAsTuples();
[RequiresUnreferencedCode(
"The use of unmapped enums, ranges or multiranges requires reflection usage which is incompatible with trimming.")]
[RequiresDynamicCode(
"The use of unmapped enums, ranges or multiranges requires dynamic code usage which is incompatible with NativeAOT.")]
INpgsqlTypeMapper INpgsqlTypeMapper.EnableUnmappedTypes()
=> EnableUnmappedTypes();
///
INpgsqlTypeMapper INpgsqlTypeMapper.MapEnum<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] TEnum>(string? pgName, INpgsqlNameTranslator? nameTranslator)
{
_internalBuilder.MapEnum(pgName, nameTranslator);
return this;
}
///
[RequiresDynamicCode("Calling MapEnum with a Type can require creating new generic types or methods. This may not work when AOT compiling.")]
INpgsqlTypeMapper INpgsqlTypeMapper.MapEnum([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]
Type clrType, string? pgName, INpgsqlNameTranslator? nameTranslator)
{
_internalBuilder.MapEnum(clrType, pgName, nameTranslator);
return this;
}
///
[RequiresDynamicCode("Mapping composite types involves serializing arbitrary types which can require creating new generic types or methods. This is currently unsupported with NativeAOT, vote on issue #5303 if this is important to you.")]
INpgsqlTypeMapper INpgsqlTypeMapper.MapComposite<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields)] T>(
string? pgName, INpgsqlNameTranslator? nameTranslator)
{
_internalBuilder.MapComposite(typeof(T), pgName, nameTranslator);
return this;
}
///
[RequiresDynamicCode("Mapping composite types involves serializing arbitrary types which can require creating new generic types or methods. This is currently unsupported with NativeAOT, vote on issue #5303 if this is important to you.")]
INpgsqlTypeMapper INpgsqlTypeMapper.MapComposite([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicFields)]
Type clrType, string? pgName, INpgsqlNameTranslator? nameTranslator)
{
_internalBuilder.MapComposite(clrType, pgName, nameTranslator);
return this;
}
}