591 lines
21 KiB
C#
591 lines
21 KiB
C#
using System;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Data.Common;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Npgsql.Internal;
|
|
using Npgsql.Internal.TypeHandling;
|
|
using Npgsql.PostgresTypes;
|
|
using Npgsql.TypeMapping;
|
|
using Npgsql.Util;
|
|
using NpgsqlTypes;
|
|
using static Npgsql.Util.Statics;
|
|
|
|
namespace Npgsql;
|
|
|
|
///<summary>
|
|
/// This class represents a parameter to a command that will be sent to server
|
|
///</summary>
|
|
public class NpgsqlParameter : DbParameter, IDbDataParameter, ICloneable
|
|
{
|
|
#region Fields and Properties
|
|
|
|
private protected byte _precision;
|
|
private protected byte _scale;
|
|
private protected int _size;
|
|
|
|
// ReSharper disable InconsistentNaming
|
|
private protected NpgsqlDbType? _npgsqlDbType;
|
|
private protected string? _dataTypeName;
|
|
// ReSharper restore InconsistentNaming
|
|
|
|
private protected string _name = string.Empty;
|
|
private protected object? _value;
|
|
private protected string _sourceColumn;
|
|
|
|
internal string TrimmedName { get; private protected set; } = PositionalName;
|
|
internal const string PositionalName = "";
|
|
|
|
/// <summary>
|
|
/// Can be used to communicate a value from the validation phase to the writing phase.
|
|
/// To be used by type handlers only.
|
|
/// </summary>
|
|
public object? ConvertedValue { get; set; }
|
|
|
|
internal NpgsqlLengthCache? LengthCache { get; set; }
|
|
|
|
internal NpgsqlTypeHandler? Handler { get; set; }
|
|
|
|
internal FormatCode FormatCode { get; private set; }
|
|
|
|
#endregion
|
|
|
|
#region Constructors
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="NpgsqlParameter"/> class.
|
|
/// </summary>
|
|
public NpgsqlParameter()
|
|
{
|
|
_sourceColumn = string.Empty;
|
|
Direction = ParameterDirection.Input;
|
|
SourceVersion = DataRowVersion.Current;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="NpgsqlParameter"/> class with the parameter name and a value.
|
|
/// </summary>
|
|
/// <param name="parameterName">The name of the parameter to map.</param>
|
|
/// <param name="value">The value of the <see cref="NpgsqlParameter"/>.</param>
|
|
/// <remarks>
|
|
/// <p>
|
|
/// When you specify an <see cref="object"/> in the value parameter, the <see cref="System.Data.DbType"/> is
|
|
/// inferred from the CLR type.
|
|
/// </p>
|
|
/// <p>
|
|
/// When using this constructor, you must be aware of a possible misuse of the constructor which takes a <see cref="DbType"/>
|
|
/// parameter. This happens when calling this constructor passing an int 0 and the compiler thinks you are passing a value of
|
|
/// <see cref="DbType"/>. Use <see cref="Convert.ToInt32(object)"/> for example to have compiler calling the correct constructor.
|
|
/// </p>
|
|
/// </remarks>
|
|
public NpgsqlParameter(string? parameterName, object? value)
|
|
: this()
|
|
{
|
|
ParameterName = parameterName;
|
|
// ReSharper disable once VirtualMemberCallInConstructor
|
|
Value = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="NpgsqlParameter"/> class with the parameter name and the data type.
|
|
/// </summary>
|
|
/// <param name="parameterName">The name of the parameter to map.</param>
|
|
/// <param name="parameterType">One of the <see cref="NpgsqlTypes.NpgsqlDbType"/> values.</param>
|
|
public NpgsqlParameter(string? parameterName, NpgsqlDbType parameterType)
|
|
: this(parameterName, parameterType, 0, string.Empty)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="NpgsqlParameter"/>.
|
|
/// </summary>
|
|
/// <param name="parameterName">The name of the parameter to map.</param>
|
|
/// <param name="parameterType">One of the <see cref="System.Data.DbType"/> values.</param>
|
|
public NpgsqlParameter(string? parameterName, DbType parameterType)
|
|
: this(parameterName, parameterType, 0, string.Empty)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="NpgsqlParameter"/>.
|
|
/// </summary>
|
|
/// <param name="parameterName">The name of the parameter to map.</param>
|
|
/// <param name="parameterType">One of the <see cref="NpgsqlTypes.NpgsqlDbType"/> values.</param>
|
|
/// <param name="size">The length of the parameter.</param>
|
|
public NpgsqlParameter(string? parameterName, NpgsqlDbType parameterType, int size)
|
|
: this(parameterName, parameterType, size, string.Empty)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="NpgsqlParameter"/>.
|
|
/// </summary>
|
|
/// <param name="parameterName">The name of the parameter to map.</param>
|
|
/// <param name="parameterType">One of the <see cref="System.Data.DbType"/> values.</param>
|
|
/// <param name="size">The length of the parameter.</param>
|
|
public NpgsqlParameter(string? parameterName, DbType parameterType, int size)
|
|
: this(parameterName, parameterType, size, string.Empty)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="NpgsqlParameter"/>
|
|
/// </summary>
|
|
/// <param name="parameterName">The name of the parameter to map.</param>
|
|
/// <param name="parameterType">One of the <see cref="NpgsqlTypes.NpgsqlDbType"/> values.</param>
|
|
/// <param name="size">The length of the parameter.</param>
|
|
/// <param name="sourceColumn">The name of the source column.</param>
|
|
public NpgsqlParameter(string? parameterName, NpgsqlDbType parameterType, int size, string? sourceColumn)
|
|
{
|
|
ParameterName = parameterName;
|
|
NpgsqlDbType = parameterType;
|
|
_size = size;
|
|
_sourceColumn = sourceColumn ?? string.Empty;
|
|
Direction = ParameterDirection.Input;
|
|
SourceVersion = DataRowVersion.Current;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="NpgsqlParameter"/>.
|
|
/// </summary>
|
|
/// <param name="parameterName">The name of the parameter to map.</param>
|
|
/// <param name="parameterType">One of the <see cref="System.Data.DbType"/> values.</param>
|
|
/// <param name="size">The length of the parameter.</param>
|
|
/// <param name="sourceColumn">The name of the source column.</param>
|
|
public NpgsqlParameter(string? parameterName, DbType parameterType, int size, string? sourceColumn)
|
|
{
|
|
ParameterName = parameterName;
|
|
DbType = parameterType;
|
|
_size = size;
|
|
_sourceColumn = sourceColumn ?? string.Empty;
|
|
Direction = ParameterDirection.Input;
|
|
SourceVersion = DataRowVersion.Current;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="NpgsqlParameter"/>.
|
|
/// </summary>
|
|
/// <param name="parameterName">The name of the parameter to map.</param>
|
|
/// <param name="parameterType">One of the <see cref="NpgsqlTypes.NpgsqlDbType"/> values.</param>
|
|
/// <param name="size">The length of the parameter.</param>
|
|
/// <param name="sourceColumn">The name of the source column.</param>
|
|
/// <param name="direction">One of the <see cref="System.Data.ParameterDirection"/> values.</param>
|
|
/// <param name="isNullable">
|
|
/// <see langword="true"/> if the value of the field can be <see langword="null"/>, otherwise <see langword="false"/>.
|
|
/// </param>
|
|
/// <param name="precision">
|
|
/// The total number of digits to the left and right of the decimal point to which <see cref="Value"/> is resolved.
|
|
/// </param>
|
|
/// <param name="scale">The total number of decimal places to which <see cref="Value"/> is resolved.</param>
|
|
/// <param name="sourceVersion">One of the <see cref="System.Data.DataRowVersion"/> values.</param>
|
|
/// <param name="value">An <see cref="object"/> that is the value of the <see cref="NpgsqlParameter"/>.</param>
|
|
public NpgsqlParameter(string parameterName, NpgsqlDbType parameterType, int size, string? sourceColumn,
|
|
ParameterDirection direction, bool isNullable, byte precision, byte scale,
|
|
DataRowVersion sourceVersion, object value)
|
|
{
|
|
ParameterName = parameterName;
|
|
Size = size;
|
|
_sourceColumn = sourceColumn ?? string.Empty;
|
|
Direction = direction;
|
|
IsNullable = isNullable;
|
|
Precision = precision;
|
|
Scale = scale;
|
|
SourceVersion = sourceVersion;
|
|
// ReSharper disable once VirtualMemberCallInConstructor
|
|
Value = value;
|
|
|
|
NpgsqlDbType = parameterType;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="NpgsqlParameter"/>.
|
|
/// </summary>
|
|
/// <param name="parameterName">The name of the parameter to map.</param>
|
|
/// <param name="parameterType">One of the <see cref="System.Data.DbType"/> values.</param>
|
|
/// <param name="size">The length of the parameter.</param>
|
|
/// <param name="sourceColumn">The name of the source column.</param>
|
|
/// <param name="direction">One of the <see cref="System.Data.ParameterDirection"/> values.</param>
|
|
/// <param name="isNullable">
|
|
/// <see langword="true"/> if the value of the field can be <see langword="null"/>, otherwise <see langword="false"/>.
|
|
/// </param>
|
|
/// <param name="precision">
|
|
/// The total number of digits to the left and right of the decimal point to which <see cref="Value"/> is resolved.
|
|
/// </param>
|
|
/// <param name="scale">The total number of decimal places to which <see cref="Value"/> is resolved.</param>
|
|
/// <param name="sourceVersion">One of the <see cref="System.Data.DataRowVersion"/> values.</param>
|
|
/// <param name="value">An <see cref="object"/> that is the value of the <see cref="NpgsqlParameter"/>.</param>
|
|
public NpgsqlParameter(string parameterName, DbType parameterType, int size, string? sourceColumn,
|
|
ParameterDirection direction, bool isNullable, byte precision, byte scale,
|
|
DataRowVersion sourceVersion, object value)
|
|
{
|
|
ParameterName = parameterName;
|
|
Size = size;
|
|
_sourceColumn = sourceColumn ?? string.Empty;
|
|
Direction = direction;
|
|
IsNullable = isNullable;
|
|
Precision = precision;
|
|
Scale = scale;
|
|
SourceVersion = sourceVersion;
|
|
// ReSharper disable once VirtualMemberCallInConstructor
|
|
Value = value;
|
|
DbType = parameterType;
|
|
}
|
|
#endregion
|
|
|
|
#region Name
|
|
|
|
/// <summary>
|
|
/// Gets or sets The name of the <see cref="NpgsqlParameter"/>.
|
|
/// </summary>
|
|
/// <value>The name of the <see cref="NpgsqlParameter"/>.
|
|
/// The default is an empty string.</value>
|
|
[AllowNull, DefaultValue("")]
|
|
public sealed override string ParameterName
|
|
{
|
|
get => _name;
|
|
set
|
|
{
|
|
if (Collection is not null)
|
|
Collection.ChangeParameterName(this, value);
|
|
else
|
|
ChangeParameterName(value);
|
|
}
|
|
}
|
|
|
|
internal void ChangeParameterName(string? value)
|
|
{
|
|
if (value == null)
|
|
_name = TrimmedName = PositionalName;
|
|
else if (value.Length > 0 && (value[0] == ':' || value[0] == '@'))
|
|
TrimmedName = (_name = value).Substring(1);
|
|
else
|
|
_name = TrimmedName = value;
|
|
}
|
|
|
|
internal bool IsPositional => ParameterName.Length == 0;
|
|
|
|
#endregion Name
|
|
|
|
#region Value
|
|
|
|
/// <inheritdoc />
|
|
[TypeConverter(typeof(StringConverter)), Category("Data")]
|
|
public override object? Value
|
|
{
|
|
get => _value;
|
|
set
|
|
{
|
|
if (_value == null || value == null || _value.GetType() != value.GetType())
|
|
Handler = null;
|
|
_value = value;
|
|
ConvertedValue = null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the value of the parameter.
|
|
/// </summary>
|
|
/// <value>
|
|
/// An <see cref="object" /> that is the value of the parameter.
|
|
/// The default value is <see langword="null" />.
|
|
/// </value>
|
|
[Category("Data")]
|
|
[TypeConverter(typeof(StringConverter))]
|
|
public object? NpgsqlValue
|
|
{
|
|
get => Value;
|
|
set => Value = value;
|
|
}
|
|
|
|
#endregion Value
|
|
|
|
#region Type
|
|
|
|
/// <summary>
|
|
/// Gets or sets the <see cref="System.Data.DbType"/> of the parameter.
|
|
/// </summary>
|
|
/// <value>One of the <see cref="System.Data.DbType"/> values. The default is <see cref="object"/>.</value>
|
|
[DefaultValue(DbType.Object)]
|
|
[Category("Data"), RefreshProperties(RefreshProperties.All)]
|
|
public sealed override DbType DbType
|
|
{
|
|
get
|
|
{
|
|
if (_npgsqlDbType.HasValue)
|
|
return GlobalTypeMapper.NpgsqlDbTypeToDbType(_npgsqlDbType.Value);
|
|
|
|
if (_dataTypeName is not null)
|
|
return GlobalTypeMapper.NpgsqlDbTypeToDbType(GlobalTypeMapper.DataTypeNameToNpgsqlDbType(_dataTypeName));
|
|
|
|
if (Value is not null) // Infer from value but don't cache
|
|
{
|
|
return GlobalTypeMapper.Instance.TryResolveMappingByValue(Value, out var mapping)
|
|
? mapping.DbType
|
|
: DbType.Object;
|
|
}
|
|
|
|
return DbType.Object;
|
|
}
|
|
set
|
|
{
|
|
Handler = null;
|
|
_npgsqlDbType = value == DbType.Object
|
|
? null
|
|
: GlobalTypeMapper.DbTypeToNpgsqlDbType(value)
|
|
?? throw new NotSupportedException($"The parameter type DbType.{value} isn't supported by PostgreSQL or Npgsql");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the <see cref="NpgsqlTypes.NpgsqlDbType"/> of the parameter.
|
|
/// </summary>
|
|
/// <value>One of the <see cref="NpgsqlTypes.NpgsqlDbType"/> values. The default is <see cref="NpgsqlTypes.NpgsqlDbType"/>.</value>
|
|
[DefaultValue(NpgsqlDbType.Unknown)]
|
|
[Category("Data"), RefreshProperties(RefreshProperties.All)]
|
|
[DbProviderSpecificTypeProperty(true)]
|
|
public NpgsqlDbType NpgsqlDbType
|
|
{
|
|
[RequiresUnreferencedCodeAttribute("The NpgsqlDbType getter isn't trimming-safe")]
|
|
get
|
|
{
|
|
if (_npgsqlDbType.HasValue)
|
|
return _npgsqlDbType.Value;
|
|
|
|
if (_dataTypeName is not null)
|
|
return GlobalTypeMapper.DataTypeNameToNpgsqlDbType(_dataTypeName);
|
|
|
|
if (Value is not null) // Infer from value
|
|
{
|
|
return GlobalTypeMapper.Instance.TryResolveMappingByValue(Value, out var mapping)
|
|
? mapping.NpgsqlDbType ?? NpgsqlDbType.Unknown
|
|
: throw new NotSupportedException("Can't infer NpgsqlDbType for type " + Value.GetType());
|
|
}
|
|
|
|
return NpgsqlDbType.Unknown;
|
|
}
|
|
set
|
|
{
|
|
if (value == NpgsqlDbType.Array)
|
|
throw new ArgumentOutOfRangeException(nameof(value), "Cannot set NpgsqlDbType to just Array, Binary-Or with the element type (e.g. Array of Box is NpgsqlDbType.Array | NpgsqlDbType.Box).");
|
|
if (value == NpgsqlDbType.Range)
|
|
throw new ArgumentOutOfRangeException(nameof(value), "Cannot set NpgsqlDbType to just Range, Binary-Or with the element type (e.g. Range of integer is NpgsqlDbType.Range | NpgsqlDbType.Integer)");
|
|
|
|
Handler = null;
|
|
_npgsqlDbType = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Used to specify which PostgreSQL type will be sent to the database for this parameter.
|
|
/// </summary>
|
|
public string? DataTypeName
|
|
{
|
|
get
|
|
{
|
|
if (_dataTypeName != null)
|
|
return _dataTypeName;
|
|
|
|
if (_npgsqlDbType.HasValue)
|
|
return GlobalTypeMapper.NpgsqlDbTypeToDataTypeName(_npgsqlDbType.Value);
|
|
|
|
if (Value != null) // Infer from value
|
|
{
|
|
return GlobalTypeMapper.Instance.TryResolveMappingByValue(Value, out var mapping)
|
|
? mapping.DataTypeName
|
|
: null;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
set
|
|
{
|
|
_dataTypeName = value;
|
|
Handler = null;
|
|
}
|
|
}
|
|
|
|
#endregion Type
|
|
|
|
#region Other Properties
|
|
|
|
/// <inheritdoc />
|
|
public sealed override bool IsNullable { get; set; }
|
|
|
|
/// <inheritdoc />
|
|
[DefaultValue(ParameterDirection.Input)]
|
|
[Category("Data")]
|
|
public sealed override ParameterDirection Direction { get; set; }
|
|
|
|
#pragma warning disable CS0109
|
|
/// <summary>
|
|
/// Gets or sets the maximum number of digits used to represent the <see cref="Value"/> property.
|
|
/// </summary>
|
|
/// <value>
|
|
/// The maximum number of digits used to represent the <see cref="Value"/> property.
|
|
/// The default value is 0, which indicates that the data provider sets the precision for <see cref="Value"/>.</value>
|
|
[DefaultValue((byte)0)]
|
|
[Category("Data")]
|
|
public new byte Precision
|
|
{
|
|
get => _precision;
|
|
set
|
|
{
|
|
_precision = value;
|
|
Handler = null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the number of decimal places to which <see cref="Value"/> is resolved.
|
|
/// </summary>
|
|
/// <value>The number of decimal places to which <see cref="Value"/> is resolved. The default is 0.</value>
|
|
[DefaultValue((byte)0)]
|
|
[Category("Data")]
|
|
public new byte Scale
|
|
{
|
|
get => _scale;
|
|
set
|
|
{
|
|
_scale = value;
|
|
Handler = null;
|
|
}
|
|
}
|
|
#pragma warning restore CS0109
|
|
|
|
/// <inheritdoc />
|
|
[DefaultValue(0)]
|
|
[Category("Data")]
|
|
public sealed override int Size
|
|
{
|
|
get => _size;
|
|
set
|
|
{
|
|
if (value < -1)
|
|
throw new ArgumentException($"Invalid parameter Size value '{value}'. The value must be greater than or equal to 0.");
|
|
|
|
_size = value;
|
|
Handler = null;
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
[AllowNull, DefaultValue("")]
|
|
[Category("Data")]
|
|
public sealed override string SourceColumn
|
|
{
|
|
get => _sourceColumn;
|
|
set => _sourceColumn = value ?? string.Empty;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
[Category("Data"), DefaultValue(DataRowVersion.Current)]
|
|
public sealed override DataRowVersion SourceVersion { get; set; }
|
|
|
|
/// <inheritdoc />
|
|
public sealed override bool SourceColumnNullMapping { get; set; }
|
|
|
|
#pragma warning disable CA2227
|
|
/// <summary>
|
|
/// The collection to which this parameter belongs, if any.
|
|
/// </summary>
|
|
public NpgsqlParameterCollection? Collection { get; set; }
|
|
#pragma warning restore CA2227
|
|
|
|
/// <summary>
|
|
/// The PostgreSQL data type, such as int4 or text, as discovered from pg_type.
|
|
/// This property is automatically set if parameters have been derived via
|
|
/// <see cref="NpgsqlCommandBuilder.DeriveParameters"/> and can be used to
|
|
/// acquire additional information about the parameters' data type.
|
|
/// </summary>
|
|
public PostgresType? PostgresType { get; internal set; }
|
|
|
|
#endregion Other Properties
|
|
|
|
#region Internals
|
|
|
|
internal virtual void ResolveHandler(ConnectorTypeMapper typeMapper)
|
|
{
|
|
if (Handler is not null)
|
|
return;
|
|
|
|
if (_npgsqlDbType.HasValue)
|
|
Handler = typeMapper.ResolveByNpgsqlDbType(_npgsqlDbType.Value);
|
|
else if (_dataTypeName is not null)
|
|
Handler = typeMapper.ResolveByDataTypeName(_dataTypeName);
|
|
else if (_value is not null)
|
|
Handler = typeMapper.ResolveByValue(_value);
|
|
else
|
|
throw new InvalidOperationException($"Parameter '{ParameterName}' must have its value set");
|
|
}
|
|
|
|
internal void Bind(ConnectorTypeMapper typeMapper)
|
|
{
|
|
ResolveHandler(typeMapper);
|
|
FormatCode = Handler!.PreferTextWrite ? FormatCode.Text : FormatCode.Binary;
|
|
}
|
|
|
|
internal virtual int ValidateAndGetLength()
|
|
{
|
|
if (_value is DBNull)
|
|
return 0;
|
|
if (_value == null)
|
|
throw new InvalidCastException($"Parameter {ParameterName} must be set");
|
|
|
|
var lengthCache = LengthCache;
|
|
var len = Handler!.ValidateObjectAndGetLength(_value, ref lengthCache, this);
|
|
LengthCache = lengthCache;
|
|
return len;
|
|
}
|
|
|
|
internal virtual Task WriteWithLength(NpgsqlWriteBuffer buf, bool async, CancellationToken cancellationToken = default)
|
|
=> Handler!.WriteObjectWithLength(_value!, buf, LengthCache, this, async, cancellationToken);
|
|
|
|
/// <inheritdoc />
|
|
public override void ResetDbType()
|
|
{
|
|
_npgsqlDbType = null;
|
|
_dataTypeName = null;
|
|
Handler = null;
|
|
}
|
|
|
|
internal bool IsInputDirection => Direction == ParameterDirection.InputOutput || Direction == ParameterDirection.Input;
|
|
|
|
internal bool IsOutputDirection => Direction == ParameterDirection.InputOutput || Direction == ParameterDirection.Output;
|
|
|
|
#endregion
|
|
|
|
#region Clone
|
|
|
|
/// <summary>
|
|
/// Creates a new <see cref="NpgsqlParameter"/> that is a copy of the current instance.
|
|
/// </summary>
|
|
/// <returns>A new <see cref="NpgsqlParameter"/> that is a copy of this instance.</returns>
|
|
public NpgsqlParameter Clone() => CloneCore();
|
|
|
|
private protected virtual NpgsqlParameter CloneCore() =>
|
|
// use fields instead of properties
|
|
// to avoid auto-initializing something like type_info
|
|
new()
|
|
{
|
|
_precision = _precision,
|
|
_scale = _scale,
|
|
_size = _size,
|
|
_npgsqlDbType = _npgsqlDbType,
|
|
_dataTypeName = _dataTypeName,
|
|
Direction = Direction,
|
|
IsNullable = IsNullable,
|
|
_name = _name,
|
|
TrimmedName = TrimmedName,
|
|
SourceColumn = SourceColumn,
|
|
SourceVersion = SourceVersion,
|
|
_value = _value,
|
|
SourceColumnNullMapping = SourceColumnNullMapping,
|
|
};
|
|
|
|
object ICloneable.Clone() => Clone();
|
|
|
|
#endregion
|
|
}
|