From 2b3324ec9ddaeaa5fd7254931e2d987b2eda2d31 Mon Sep 17 00:00:00 2001 From: Kaur-Parminder Date: Fri, 15 Oct 2021 13:18:04 -0700 Subject: [PATCH 1/7] Moved to Shared - SqlParameter --- .../src/Microsoft.Data.SqlClient.csproj | 4 +- .../Microsoft/Data/SqlClient/SqlParameter.cs | 2351 ----------------- .../netcore/src/Resources/Strings.Designer.cs | 18 + .../netcore/src/Resources/Strings.resx | 6 + .../netcore/src/Resources/StringsHelper.cs | 1 + .../netfx/src/Microsoft.Data.SqlClient.csproj | 4 +- .../Microsoft/Data/SqlClient/SqlParameter.cs | 176 +- 7 files changed, 142 insertions(+), 2418 deletions(-) delete mode 100644 src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlParameter.cs rename src/Microsoft.Data.SqlClient/{netfx => }/src/Microsoft/Data/SqlClient/SqlParameter.cs (91%) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj index 4acd15dadc..e530cfb8b2 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -535,7 +535,9 @@ - + + Microsoft\Data\SqlClient\SqlParameter.cs + diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlParameter.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlParameter.cs deleted file mode 100644 index 5d437018c3..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlParameter.cs +++ /dev/null @@ -1,2351 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.ComponentModel.Design.Serialization; -using System.Data; -using System.Data.Common; -using System.Data.SqlTypes; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Reflection; -using System.Text; -using System.Threading; -using System.Xml; -using Microsoft.Data.Common; -using Microsoft.Data.SqlClient.Server; - -namespace Microsoft.Data.SqlClient -{ - internal abstract class DataFeed - { - } - - internal class StreamDataFeed : DataFeed - { - internal Stream _source; - - internal StreamDataFeed(Stream source) - { - _source = source; - } - } - - internal class TextDataFeed : DataFeed - { - private static UnicodeEncoding s_defaultEncoding; - internal TextReader _source; - - internal TextDataFeed(TextReader source) - { - _source = source; - } - - internal static UnicodeEncoding DefaultEncoding - { - get - { - UnicodeEncoding encoding = s_defaultEncoding; - if (encoding is null) - { - encoding = new UnicodeEncoding(false, false); - encoding = Interlocked.CompareExchange(ref s_defaultEncoding, encoding, null) ?? encoding; - } - return encoding; - } - } - } - - internal class XmlDataFeed : DataFeed - { - internal XmlReader _source; - - internal XmlDataFeed(XmlReader source) - { - _source = source; - } - } - - /// - [TypeConverter(typeof(SqlParameter.SqlParameterConverter))] - public sealed partial class SqlParameter : DbParameter, IDbDataParameter, ICloneable - { - internal sealed class SqlParameterConverter : ExpandableObjectConverter - { - - // converter classes should have public ctor - public SqlParameterConverter() - { - } - - public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) - { - if (typeof(InstanceDescriptor) == destinationType) - { - return true; - } - return base.CanConvertTo(context, destinationType); - } - - public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) - { - if (destinationType == null) - { - throw ADP.ArgumentNull(nameof(destinationType)); - } - if ((typeof(InstanceDescriptor) == destinationType) && (value is SqlParameter)) - { - return ConvertToInstanceDescriptor(value as SqlParameter); - } - return base.ConvertTo(context, culture, value, destinationType); - } - - private InstanceDescriptor ConvertToInstanceDescriptor(SqlParameter p) - { - int flags = 0; // if part of the collection - the parametername can't be empty - - if (p.ShouldSerializeSqlDbType()) - { - flags |= 1; - } - if (p.ShouldSerializeSize()) - { - flags |= 2; - } - if (!string.IsNullOrEmpty(p.SourceColumn)) - { - flags |= 4; - } - if (null != p.Value) - { - flags |= 8; - } - if ( - (ParameterDirection.Input != p.Direction) || - p.IsNullable || - p.ShouldSerializePrecision() || - p.ShouldSerializeScale() || - (DataRowVersion.Current != p.SourceVersion) - ) - { - flags |= 16; // v1.0 everything - } - - if ( - p.SourceColumnNullMapping || - !string.IsNullOrEmpty(p.XmlSchemaCollectionDatabase) || - !string.IsNullOrEmpty(p.XmlSchemaCollectionOwningSchema) || - !string.IsNullOrEmpty(p.XmlSchemaCollectionName) - ) - { - flags |= 32; // v2.0 everything - } - - Type[] ctorParams; - object[] ctorValues; - switch (flags) - { - case 0: // ParameterName - case 1: // SqlDbType - ctorParams = new Type[] { typeof(string), typeof(SqlDbType) }; - ctorValues = new object[] { p.ParameterName, p.SqlDbType }; - break; - case 2: // Size - case 3: // Size, SqlDbType - ctorParams = new Type[] { typeof(string), typeof(SqlDbType), typeof(int) }; - ctorValues = new object[] { p.ParameterName, p.SqlDbType, p.Size }; - break; - case 4: // SourceColumn - case 5: // SourceColumn, SqlDbType - case 6: // SourceColumn, Size - case 7: // SourceColumn, Size, SqlDbType - ctorParams = new Type[] { typeof(string), typeof(SqlDbType), typeof(int), typeof(string) }; - ctorValues = new object[] { p.ParameterName, p.SqlDbType, p.Size, p.SourceColumn }; - break; - case 8: // Value - ctorParams = new Type[] { typeof(string), typeof(object) }; - ctorValues = new object[] { p.ParameterName, p.Value }; - break; - default: - if (0 == (32 & flags)) - { // v1.0 everything - ctorParams = new Type[] { - typeof(string), typeof(SqlDbType), typeof(int), typeof(ParameterDirection), - typeof(bool), typeof(byte), typeof(byte), - typeof(string), typeof(DataRowVersion), - typeof(object) }; - ctorValues = new object[] { - p.ParameterName, p.SqlDbType, p.Size, p.Direction, - p.IsNullable, p.PrecisionInternal, p.ScaleInternal, - p.SourceColumn, p.SourceVersion, - p.Value }; - } - else - { // v2.0 everything - round trip all browsable properties + precision/scale - ctorParams = new Type[] { - typeof(string), typeof(SqlDbType), typeof(int), typeof(ParameterDirection), - typeof(byte), typeof(byte), - typeof(string), typeof(DataRowVersion), typeof(bool), - typeof(object), - typeof(string), typeof(string), - typeof(string) }; - ctorValues = new object[] { - p.ParameterName, p.SqlDbType, p.Size, p.Direction, - p.PrecisionInternal, p.ScaleInternal, - p.SourceColumn, p.SourceVersion, p.SourceColumnNullMapping, - p.Value, - p.XmlSchemaCollectionDatabase, p.XmlSchemaCollectionOwningSchema, - p.XmlSchemaCollectionName}; - } - break; - } - ConstructorInfo ctor = typeof(SqlParameter).GetConstructor(ctorParams); - return new InstanceDescriptor(ctor, ctorValues); - } - } - - [Flags] - private enum SqlParameterFlags : ushort - { - None = 0, - IsNull = 1, - IsNullable = 2, - IsSqlParameterSqlType = 4, - SourceColumnNullMapping = 8, - CoercedValueIsSqlType = 16, - CoercedValueIsDataFeed = 32, - HasReceivedMetadata = 64, - ForceColumnEncryption = 128, - IsDerivedParameterTypeName = 256, - HasScale = 512, - } - - private MetaType _metaType; - private SqlCollation _collation; - private SqlMetaDataXmlSchemaCollection _xmlSchemaCollection; - private string _udtTypeName; - private string _typeName; - private Exception _udtLoadError; - private string _parameterName; - private byte _precision; - private byte _scale; - private MetaType _internalMetaType; - private SqlBuffer _sqlBufferReturnValue; - private INullable _valueAsINullable; - private int _actualSize; - private object _value; - private object _coercedValue; - private object _parent; - private ParameterDirection _direction; - private int _size; - private int _offset; - private string _sourceColumn; - private DataRowVersion _sourceVersion; - private SqlParameterFlags _flags; - - /// - public SqlParameter() : base() - { - _flags = SqlParameterFlags.IsNull; - _actualSize = -1; - _direction = ParameterDirection.Input; - } - - /// - public SqlParameter(string parameterName, SqlDbType dbType) : this() - { - ParameterName = parameterName; - SqlDbType = dbType; - } - - /// - public SqlParameter(string parameterName, object value) : this() - { - Debug.Assert(!(value is SqlDbType), "use SqlParameter(string, SqlDbType)"); - - ParameterName = parameterName; - Value = value; - } - - /// - public SqlParameter(string parameterName, SqlDbType dbType, int size) : this() - { - ParameterName = parameterName; - SqlDbType = dbType; - Size = size; - } - - /// - public SqlParameter(string parameterName, SqlDbType dbType, int size, string sourceColumn) : this() - { - ParameterName = parameterName; - SqlDbType = dbType; - Size = size; - SourceColumn = sourceColumn; - } - - /// - [EditorBrowsable(EditorBrowsableState.Advanced)] - public SqlParameter( - string parameterName, - SqlDbType dbType, - int size, - ParameterDirection direction, - bool isNullable, - byte precision, - byte scale, - string sourceColumn, - DataRowVersion sourceVersion, - object value - ) - : this(parameterName, dbType, size, sourceColumn) - { - Direction = direction; - IsNullable = isNullable; - Precision = precision; - Scale = scale; - SourceVersion = sourceVersion; - Value = value; - } - - /// - public SqlParameter( - string parameterName, - SqlDbType dbType, - int size, - ParameterDirection direction, - byte precision, - byte scale, - string sourceColumn, - DataRowVersion sourceVersion, - bool sourceColumnNullMapping, - object value, - string xmlSchemaCollectionDatabase, - string xmlSchemaCollectionOwningSchema, - string xmlSchemaCollectionName - ) - : this() - { - ParameterName = parameterName; - SqlDbType = dbType; - Size = size; - Direction = direction; - Precision = precision; - Scale = scale; - SourceColumn = sourceColumn; - SourceVersion = sourceVersion; - SourceColumnNullMapping = sourceColumnNullMapping; - Value = value; - if (!string.IsNullOrEmpty(xmlSchemaCollectionDatabase) || !string.IsNullOrEmpty(xmlSchemaCollectionOwningSchema) || !string.IsNullOrEmpty(xmlSchemaCollectionName)) - { - EnsureXmlSchemaCollection(); - _xmlSchemaCollection.Database = xmlSchemaCollectionDatabase; - _xmlSchemaCollection.OwningSchema = xmlSchemaCollectionOwningSchema; - _xmlSchemaCollection.Name = xmlSchemaCollectionName; - } - } - - private SqlParameter(SqlParameter source) : this() - { - ADP.CheckArgumentNull(source, nameof(source)); - source.CloneHelper(this); - if (_value is ICloneable cloneable) - { - _value = cloneable.Clone(); - } - } - - /// - /// Get or set the encryption related metadata of this SqlParameter. - /// Should be set to a non-null value only once. - /// - internal SqlCipherMetadata CipherMetadata { get; set; } - - /// - /// Indicates if the parameter encryption metadata received by sp_describe_parameter_encryption. - /// For unencrypted parameters, the encryption metadata should still be sent (and will indicate - /// that no encryption is needed). - /// - internal bool HasReceivedMetadata - { - get => HasFlag(SqlParameterFlags.HasReceivedMetadata); - set => SetFlag(SqlParameterFlags.HasReceivedMetadata, value); - } - - /// - /// Returns the normalization rule version number as a byte - /// - internal byte NormalizationRuleVersion => CipherMetadata?.NormalizationRuleVersion ?? 0x00; - - /// - [Browsable(false)] - public SqlCompareOptions CompareInfo - { - // Bits 21 through 25 represent the CompareInfo - get - { - SqlCollation collation = _collation; - if (null != collation) - { - return collation.SqlCompareOptions; - } - return SqlCompareOptions.None; - } - set - { - SqlCollation collation = _collation; - - // Copied from SQLString.x_iValidSqlCompareOptionMask - SqlCompareOptions validSqlCompareOptionMask = - SqlCompareOptions.IgnoreCase | SqlCompareOptions.IgnoreWidth | - SqlCompareOptions.IgnoreNonSpace | SqlCompareOptions.IgnoreKanaType | - SqlCompareOptions.BinarySort | SqlCompareOptions.BinarySort2; - - if ((value & validSqlCompareOptionMask) != value) - { - throw ADP.ArgumentOutOfRange(nameof(CompareInfo)); - } - - if (collation == null || collation.SqlCompareOptions != value) - { - _collation = SqlCollation.FromLCIDAndSort(collation?.LCID ?? 0, value); - } - } - } - - /// - [ResCategory("XML")] - public string XmlSchemaCollectionDatabase - { - get => _xmlSchemaCollection?.Database ?? string.Empty; - set => EnsureXmlSchemaCollection().Database = value; - } - - /// - [ResCategory("XML")] - public string XmlSchemaCollectionOwningSchema - { - get => _xmlSchemaCollection?.OwningSchema ?? string.Empty; - set => EnsureXmlSchemaCollection().OwningSchema = value; - } - - /// - [ResCategory("XML")] - public string XmlSchemaCollectionName - { - get => _xmlSchemaCollection?.Name ?? string.Empty; - set => EnsureXmlSchemaCollection().Name = value; - } - - /// - [ - DefaultValue(false), - ResCategory("Data") - ] - public bool ForceColumnEncryption - { - get => HasFlag(SqlParameterFlags.ForceColumnEncryption); - set => SetFlag(SqlParameterFlags.ForceColumnEncryption, value); - } - - /// - public override DbType DbType - { - get => GetMetaTypeOnly().DbType; - set - { - MetaType metatype = _metaType; - if ((null == metatype) || (metatype.DbType != value)) - { - PropertyTypeChanging(); - _metaType = MetaType.GetMetaTypeFromDbType(value); - } - } - } - - /// - public override void ResetDbType() => ResetSqlDbType(); - - /// - [ResCategory("Data")] - public override string ParameterName - { - get => _parameterName ?? string.Empty; - set - { - if ( - string.IsNullOrEmpty(value) || - (value.Length < TdsEnums.MAX_PARAMETER_NAME_LENGTH) || - ( - (value[0] == '@') && - (value.Length <= TdsEnums.MAX_PARAMETER_NAME_LENGTH) - ) - ) - { - if (_parameterName != value) - { - PropertyChanging(); - _parameterName = value; - } - } - else - { - throw SQL.InvalidParameterNameLength(value); - } - } - } - - /// - [Browsable(false)] - public int LocaleId - { - // Lowest 20 bits represent LocaleId - get - { - SqlCollation collation = _collation; - if (null != collation) - { - return collation.LCID; - } - return 0; - } - set - { - SqlCollation collation = _collation; - - if (value != (SqlCollation.MaskLcid & value)) - { - throw ADP.ArgumentOutOfRange(nameof(LocaleId)); - } - - if (collation == null || collation.LCID != value) - { - _collation = SqlCollation.FromLCIDAndSort(value, collation?.SqlCompareOptions ?? SqlCompareOptions.None); - } - } - } - - /// - [ - DefaultValue((byte)0), - ResCategory("Data") - ] - public new byte Precision - { - get => PrecisionInternal; - set => PrecisionInternal = value; - } - - private bool ShouldSerializePrecision() => _precision != 0; - - /// - [ - DefaultValue((byte)0), - ResCategory("Data") - ] - public new byte Scale - { - get => ScaleInternal; - set => ScaleInternal = value; - } - - internal byte ScaleInternal - { - get - { - byte scale = _scale; - SqlDbType dbtype = GetMetaSqlDbTypeOnly(); - if ((scale == 0) && (dbtype == SqlDbType.Decimal)) - { - scale = ValueScale(SqlValue); - } - return scale; - } - set - { - if (_scale != value || !HasFlag(SqlParameterFlags.HasScale)) - { - PropertyChanging(); - _scale = value; - SetFlag(SqlParameterFlags.HasScale, true); - _actualSize = -1; // Invalidate actual size such that it is re-calculated - } - } - } - - private bool ShouldSerializeScale() => _scale != 0; // V1.0 compat, ignore _hasScale - - /// - [ - RefreshProperties(RefreshProperties.All), - ResCategory("Data"), - DbProviderSpecificTypeProperty(true) - ] - public SqlDbType SqlDbType - { - get => GetMetaTypeOnly().SqlDbType; - set - { - MetaType metatype = _metaType; - // HACK!!! - // We didn't want to expose SmallVarBinary on SqlDbType so we - // stuck it at the end of SqlDbType in v1.0, except that now - // we have new data types after that and it's smack dab in the - // middle of the valid range. To prevent folks from setting - // this invalid value we have to have this code here until we - // can take the time to fix it later. - if (TdsEnums.SmallVarBinary == value) - { - throw SQL.InvalidSqlDbType(value); - } - if ((null == metatype) || (metatype.SqlDbType != value)) - { - PropertyTypeChanging(); - _metaType = MetaType.GetMetaTypeFromSqlDbType(value, value == SqlDbType.Structured); - } - } - } - - private bool ShouldSerializeSqlDbType() => _metaType != null; - - /// - public void ResetSqlDbType() - { - if (_metaType != null) - { - PropertyTypeChanging(); - _metaType = null; - } - } - - /// - [ - Browsable(false), - DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), - ] - public object SqlValue - { - get - { - if (_udtLoadError != null) - { - throw _udtLoadError; - } - - if (_value != null) - { - if (_value == DBNull.Value) - { - return MetaType.GetNullSqlValue(GetMetaTypeOnly().SqlType); - } - if (_value is INullable) - { - return _value; - } - - // For Date and DateTime2, return the CLR object directly without converting it to a SqlValue - // GetMetaTypeOnly() will convert _value to a string in the case of char or char[], so only check - // the SqlDbType for DateTime. This is the only case when we might return the CLR value directly. - if (_value is DateTime) - { - SqlDbType sqlDbType = GetMetaTypeOnly().SqlDbType; - if (sqlDbType == SqlDbType.Date || sqlDbType == SqlDbType.DateTime2) - { - return _value; - } - } - - return (MetaType.GetSqlValueFromComVariant(_value)); - } - else if (_sqlBufferReturnValue != null) - { - return _sqlBufferReturnValue.SqlValue; - } - return null; - } - set - { - Value = value; - } - } - - /// - [ - Browsable(false), - EditorBrowsable(EditorBrowsableState.Advanced) - ] - public string UdtTypeName - { - get => _udtTypeName ?? string.Empty; - set => _udtTypeName = value; - } - - /// - [ - Browsable(false), - EditorBrowsable(EditorBrowsableState.Advanced) - ] - public string TypeName - { - get => _typeName ?? string.Empty; - set - { - _typeName = value; - IsDerivedParameterTypeName = false; - } - } - - /// - [ - RefreshProperties(RefreshProperties.All), - ResCategory("Data"), - TypeConverter(typeof(StringConverter)), - ] - public override object Value - { - get - { - if (_udtLoadError != null) - { - throw _udtLoadError; - } - - if (_value != null) - { - return _value; - } - else if (_sqlBufferReturnValue != null) - { - if (ParameterIsSqlType) - { - return _sqlBufferReturnValue.SqlValue; - } - return _sqlBufferReturnValue.Value; - } - return null; - } - set - { - _value = value; - _sqlBufferReturnValue = null; - _coercedValue = null; - _valueAsINullable = _value as INullable; - SetFlag(SqlParameterFlags.IsSqlParameterSqlType, _valueAsINullable != null); - SetFlag(SqlParameterFlags.IsNull, (null == _value) || (_value == DBNull.Value) || (HasFlag(SqlParameterFlags.IsSqlParameterSqlType) && _valueAsINullable.IsNull)); - _udtLoadError = null; - _actualSize = -1; - } - } - - /// - [ - RefreshProperties(RefreshProperties.All), - ResCategory("Data"), - ] - public override ParameterDirection Direction - { - get => _direction; - set - { - if (_direction != value) - { - switch (value) - { - case ParameterDirection.Input: - case ParameterDirection.Output: - case ParameterDirection.InputOutput: - case ParameterDirection.ReturnValue: - PropertyChanging(); - _direction = value; - break; - default: - throw ADP.InvalidParameterDirection(value); - } - } - } - } - - /// - public override bool IsNullable - { - get => HasFlag(SqlParameterFlags.IsNullable); - set => SetFlag(SqlParameterFlags.IsNullable, value); - } - - /// - public int Offset - { - get => _offset; - set - { - if (value < 0) - { - throw ADP.InvalidOffsetValue(value); - } - _offset = value; - } - } - - /// - [ResCategory("Data")] - public override int Size - { - get - { - int size = _size; - if (size == 0) - { - size = ValueSize(Value); - } - return size; - } - set - { - if (value != _size) - { - if (value < -1) - { - throw ADP.InvalidSizeValue(value); - } - PropertyChanging(); - _size = value; - } - } - } - - private void ResetSize() - { - if (_size != 0) - { - PropertyChanging(); - _size = 0; - } - } - - private bool ShouldSerializeSize() => _size != 0; - - /// - [ResCategory("Update")] - public override string SourceColumn - { - get => _sourceColumn ?? string.Empty; - set => _sourceColumn = value; - } - - /// - [ResCategory("DataCategory_Update")] - [ResDescription(StringsHelper.ResourceNames.SqlParameter_SourceColumnNullMapping)] - public override bool SourceColumnNullMapping - { - get => HasFlag(SqlParameterFlags.SourceColumnNullMapping); - set => SetFlag(SqlParameterFlags.SourceColumnNullMapping, value); - } - - /// - [ResCategory("Data")] - public override string ToString() => ParameterName; - - /// - [ResCategory(StringsHelper.ResourceNames.DataCategory_Update)] - public override DataRowVersion SourceVersion - { - get - { - DataRowVersion sourceVersion = _sourceVersion; - return (sourceVersion != 0) ? sourceVersion : DataRowVersion.Current; - } - set - { - switch (value) - { - case DataRowVersion.Original: - case DataRowVersion.Current: - case DataRowVersion.Proposed: - case DataRowVersion.Default: - _sourceVersion = value; - break; - default: - throw ADP.InvalidDataRowVersion(value); - } - } - } - - /// - object ICloneable.Clone() => new SqlParameter(this); - - private object CoercedValue - { - get => _coercedValue; - set => _coercedValue = value; - } - - internal bool CoercedValueIsDataFeed - { - get - { - if (null == _coercedValue) - { - GetCoercedValue(); - } - AssertCachedPropertiesAreValid(); - return HasFlag(SqlParameterFlags.CoercedValueIsDataFeed); - } - } - - internal bool CoercedValueIsSqlType - { - get - { - if (_coercedValue == null) - { - GetCoercedValue(); - } - AssertCachedPropertiesAreValid(); - return HasFlag(SqlParameterFlags.CoercedValueIsSqlType); - } - } - - // - // currently the user can't set this value. it gets set by the returnvalue from tds - // - internal SqlCollation Collation - { - get => _collation; - set => _collation = value; - } - - private bool HasFlag(SqlParameterFlags flag) - { - return (_flags & flag) != 0; - } - - internal bool IsNull - { - get - { - // NOTE: Udts can change their value any time - if (_internalMetaType.SqlDbType == SqlDbType.Udt) - { - SetFlag(SqlParameterFlags.IsNull, (_value == null) || (_value == DBNull.Value) || (HasFlag(SqlParameterFlags.IsSqlParameterSqlType) && _valueAsINullable.IsNull)); - } - return HasFlag(SqlParameterFlags.IsNull); - } - } - - internal MetaType InternalMetaType - { - get - { - Debug.Assert(null != _internalMetaType, "null InternalMetaType"); - return _internalMetaType; - } - set => _internalMetaType = value; - } - - internal byte PrecisionInternal - { - get - { - byte precision = _precision; - SqlDbType dbtype = GetMetaSqlDbTypeOnly(); - if ((0 == precision) && (SqlDbType.Decimal == dbtype)) - { - precision = ValuePrecision(SqlValue); - } - return precision; - } - set - { - SqlDbType sqlDbType = SqlDbType; - if (sqlDbType == SqlDbType.Decimal && value > TdsEnums.MAX_NUMERIC_PRECISION) - { - throw SQL.PrecisionValueOutOfRange(value); - } - if (_precision != value) - { - PropertyChanging(); - _precision = value; - } - } - } - - internal bool ParameterIsSqlType - { - get => HasFlag(SqlParameterFlags.IsSqlParameterSqlType); - set => SetFlag(SqlParameterFlags.IsSqlParameterSqlType, value); - } - - internal string ParameterNameFixed - { - get - { - string parameterName = ParameterName; - if ((parameterName.Length > 0) && (parameterName[0] != '@')) - { - parameterName = "@" + parameterName; - } - Debug.Assert(parameterName.Length <= TdsEnums.MAX_PARAMETER_NAME_LENGTH, "parameter name too long"); - return parameterName; - } - } - - internal INullable ValueAsINullable => _valueAsINullable; - - internal bool IsDerivedParameterTypeName - { - get => HasFlag(SqlParameterFlags.IsDerivedParameterTypeName); - set => SetFlag(SqlParameterFlags.IsDerivedParameterTypeName, value); - } - - private void CloneHelper(SqlParameter destination) - { - // NOTE: _parent is not cloned - destination._value = _value; - destination._direction = _direction; - destination._size = _size; - destination._offset = _offset; - destination._sourceColumn = _sourceColumn; - destination._sourceVersion = _sourceVersion; - destination._flags = _flags & ( - SqlParameterFlags.SourceColumnNullMapping | - SqlParameterFlags.IsNull | - SqlParameterFlags.IsNullable | - SqlParameterFlags.IsSqlParameterSqlType | - SqlParameterFlags.CoercedValueIsDataFeed | - SqlParameterFlags.CoercedValueIsSqlType | - SqlParameterFlags.ForceColumnEncryption | - SqlParameterFlags.IsDerivedParameterTypeName - // HasScale and HasReceivedMetadata deliberately omitted - ); - destination._metaType = _metaType; - destination._collation = _collation; - if (_xmlSchemaCollection != null) - { - destination.EnsureXmlSchemaCollection().CopyFrom(_xmlSchemaCollection); - } - destination._udtTypeName = _udtTypeName; - destination._typeName = _typeName; - destination._udtLoadError = _udtLoadError; - destination._parameterName = _parameterName; - destination._precision = _precision; - destination._scale = _scale; - destination._sqlBufferReturnValue = _sqlBufferReturnValue; - destination._internalMetaType = _internalMetaType; - destination.CoercedValue = CoercedValue; // copy cached value reference because of XmlReader problem - destination._valueAsINullable = _valueAsINullable; - destination._actualSize = _actualSize; - } - - internal void CopyTo(SqlParameter destination) - { - ADP.CheckArgumentNull(destination, nameof(destination)); - CloneHelper(destination); - } - - internal object CompareExchangeParent(object value, object comparand) - { - object parent = _parent; - if (comparand == parent) - { - _parent = value; - } - return parent; - } - - private SqlMetaDataXmlSchemaCollection EnsureXmlSchemaCollection() - { - if (_xmlSchemaCollection is null) - { - _xmlSchemaCollection = new SqlMetaDataXmlSchemaCollection(); - } - return _xmlSchemaCollection; - } - - internal void FixStreamDataForNonPLP() - { - object value = GetCoercedValue(); - AssertCachedPropertiesAreValid(); - if (!HasFlag(SqlParameterFlags.CoercedValueIsDataFeed)) - { - return; - } - - SetFlag(SqlParameterFlags.CoercedValueIsDataFeed, false); - - if (value is TextDataFeed textFeed) - { - if (Size > 0) - { - char[] buffer = new char[Size]; - int nRead = textFeed._source.ReadBlock(buffer, 0, Size); - CoercedValue = new string(buffer, 0, nRead); - } - else - { - CoercedValue = textFeed._source.ReadToEnd(); - } - return; - } - - if (value is StreamDataFeed streamFeed) - { - if (Size > 0) - { - byte[] buffer = new byte[Size]; - int totalRead = 0; - Stream sourceStream = streamFeed._source; - while (totalRead < Size) - { - int nRead = sourceStream.Read(buffer, totalRead, Size - totalRead); - if (nRead == 0) - { - break; - } - totalRead += nRead; - } - if (totalRead < Size) - { - Array.Resize(ref buffer, totalRead); - } - CoercedValue = buffer; - } - else - { - MemoryStream ms = new MemoryStream(); - streamFeed._source.CopyTo(ms); - CoercedValue = ms.ToArray(); - } - return; - } - - if (value is XmlDataFeed xmlFeed) - { - CoercedValue = MetaType.GetStringFromXml(xmlFeed._source); - return; - } - - // We should have returned before reaching here - Debug.Fail("_coercedValueIsDataFeed was true, but the value was not a known DataFeed type"); - } - - private void GetActualFieldsAndProperties(out List fields, out SmiMetaDataPropertyCollection props, out ParameterPeekAheadValue peekAhead) - { - fields = null; - props = null; - peekAhead = null; - - object value = GetCoercedValue(); - if (value is DataTable dt) - { - if (dt.Columns.Count <= 0) - { - throw SQL.NotEnoughColumnsInStructuredType(); - } - fields = new List(dt.Columns.Count); - bool[] keyCols = new bool[dt.Columns.Count]; - bool hasKey = false; - - // set up primary key as unique key list - // do this prior to general metadata loop to favor the primary key - if (null != dt.PrimaryKey && 0 < dt.PrimaryKey.Length) - { - foreach (DataColumn col in dt.PrimaryKey) - { - keyCols[col.Ordinal] = true; - hasKey = true; - } - } - - for (int i = 0; i < dt.Columns.Count; i++) - { - fields.Add(MetaDataUtilsSmi.SmiMetaDataFromDataColumn(dt.Columns[i], dt)); - - // DataColumn uniqueness is only for a single column, so don't add - // more than one. (keyCols.Count first for assumed minimal perf benefit) - if (!hasKey && dt.Columns[i].Unique) - { - keyCols[i] = true; - hasKey = true; - } - } - - // Add unique key property, if any found. - if (hasKey) - { - props = new SmiMetaDataPropertyCollection(); - props[SmiPropertySelector.UniqueKey] = new SmiUniqueKeyProperty(new List(keyCols)); - } - } - else if (value is SqlDataReader sqlReader) - { - fields = new List(sqlReader.GetInternalSmiMetaData()); - if (fields.Count <= 0) - { - throw SQL.NotEnoughColumnsInStructuredType(); - } - - bool[] keyCols = new bool[fields.Count]; - bool hasKey = false; - for (int i = 0; i < fields.Count; i++) - { - if (fields[i] is SmiQueryMetaData qmd && !qmd.IsKey.IsNull && qmd.IsKey.Value) - { - keyCols[i] = true; - hasKey = true; - } - } - - // Add unique key property, if any found. - if (hasKey) - { - props = new SmiMetaDataPropertyCollection(); - props[SmiPropertySelector.UniqueKey] = new SmiUniqueKeyProperty(new List(keyCols)); - } - } - else if (value is IEnumerable enumerable) - { - // must grab the first record of the enumerator to get the metadata - IEnumerator enumerator = enumerable.GetEnumerator(); - SqlDataRecord firstRecord = null; - try - { - // no need for fields if there's no rows or no columns -- we'll be sending a null instance anyway. - if (enumerator.MoveNext()) - { - firstRecord = enumerator.Current; - int fieldCount = firstRecord.FieldCount; - if (0 < fieldCount) - { - // It's valid! Grab those fields. - bool[] keyCols = new bool[fieldCount]; - bool[] defaultFields = new bool[fieldCount]; - bool[] sortOrdinalSpecified = new bool[fieldCount]; - int maxSortOrdinal = -1; // largest sort ordinal seen, used to optimize locating holes in the list - bool hasKey = false; - bool hasDefault = false; - int sortCount = 0; - SmiOrderProperty.SmiColumnOrder[] sort = new SmiOrderProperty.SmiColumnOrder[fieldCount]; - fields = new List(fieldCount); - for (int i = 0; i < fieldCount; i++) - { - SqlMetaData colMeta = firstRecord.GetSqlMetaData(i); - fields.Add(MetaDataUtilsSmi.SqlMetaDataToSmiExtendedMetaData(colMeta)); - if (colMeta.IsUniqueKey) - { - keyCols[i] = true; - hasKey = true; - } - - if (colMeta.UseServerDefault) - { - defaultFields[i] = true; - hasDefault = true; - } - - sort[i].Order = colMeta.SortOrder; - if (SortOrder.Unspecified != colMeta.SortOrder) - { - // SqlMetaData takes care of checking for negative sort ordinals with specified sort order - - // bail early if there's no way sort order could be monotonically increasing - if (fieldCount <= colMeta.SortOrdinal) - { - throw SQL.SortOrdinalGreaterThanFieldCount(i, colMeta.SortOrdinal); - } - - // Check to make sure we haven't seen this ordinal before - if (sortOrdinalSpecified[colMeta.SortOrdinal]) - { - throw SQL.DuplicateSortOrdinal(colMeta.SortOrdinal); - } - - sort[i].SortOrdinal = colMeta.SortOrdinal; - sortOrdinalSpecified[colMeta.SortOrdinal] = true; - if (colMeta.SortOrdinal > maxSortOrdinal) - { - maxSortOrdinal = colMeta.SortOrdinal; - } - sortCount++; - } - } - - if (hasKey) - { - props = new SmiMetaDataPropertyCollection(); - props[SmiPropertySelector.UniqueKey] = new SmiUniqueKeyProperty(new List(keyCols)); - } - - if (hasDefault) - { - // May have already created props list in unique key handling - if (null == props) - { - props = new SmiMetaDataPropertyCollection(); - } - - props[SmiPropertySelector.DefaultFields] = new SmiDefaultFieldsProperty(new List(defaultFields)); - } - - if (0 < sortCount) - { - // validate monotonically increasing sort order. - // Since we already checked for duplicates, we just need - // to watch for values outside of the sortCount range. - if (maxSortOrdinal >= sortCount) - { - // there is at least one hole, find the first one - int i; - for (i = 0; i < sortCount; i++) - { - if (!sortOrdinalSpecified[i]) - { - break; - } - } - Debug.Assert(i < sortCount, "SqlParameter.GetActualFieldsAndProperties: SortOrdinal hole-finding algorithm failed!"); - throw SQL.MissingSortOrdinal(i); - } - - // May have already created props list - if (null == props) - { - props = new SmiMetaDataPropertyCollection(); - } - - props[SmiPropertySelector.SortOrder] = new SmiOrderProperty( - new List(sort)); - } - - // pack it up so we don't have to rewind to send the first value - peekAhead = new ParameterPeekAheadValue() - { - Enumerator = enumerator, - FirstRecord = firstRecord - }; - - // now that it's all packaged, make sure we don't dispose it. - enumerator = null; - } - else - { - throw SQL.NotEnoughColumnsInStructuredType(); - } - } - else - { - throw SQL.IEnumerableOfSqlDataRecordHasNoRows(); - } - } - finally - { - if (enumerator != null) - { - enumerator.Dispose(); - } - } - } - else if (value is DbDataReader dbReader) - { - DataTable schema = dbReader.GetSchemaTable(); - if (schema.Rows.Count <= 0) - { - throw SQL.NotEnoughColumnsInStructuredType(); - } - - int fieldCount = schema.Rows.Count; - fields = new List(fieldCount); - bool[] keyCols = new bool[fieldCount]; - bool hasKey = false; - int ordinalForIsKey = schema.Columns[SchemaTableColumn.IsKey].Ordinal; - int ordinalForColumnOrdinal = schema.Columns[SchemaTableColumn.ColumnOrdinal].Ordinal; - // Extract column metadata - for (int rowOrdinal = 0; rowOrdinal < fieldCount; rowOrdinal++) - { - DataRow row = schema.Rows[rowOrdinal]; - SmiExtendedMetaData candidateMd = MetaDataUtilsSmi.SmiMetaDataFromSchemaTableRow(row); - - // Determine destination ordinal. Allow for ordinal not specified by assuming rowOrdinal *is* columnOrdinal - // in that case, but don't worry about mix-and-match of the two techniques - int columnOrdinal = rowOrdinal; - if (!row.IsNull(ordinalForColumnOrdinal)) - { - columnOrdinal = (int)row[ordinalForColumnOrdinal]; - } - - // After this point, things we are creating (keyCols, fields) should be accessed by columnOrdinal - // while the source should just be accessed via "row". - - // Watch for out-of-range ordinals - if (columnOrdinal >= fieldCount || columnOrdinal < 0) - { - throw SQL.InvalidSchemaTableOrdinals(); - } - - // extend empty space if out-of-order ordinal - while (columnOrdinal > fields.Count) - { - fields.Add(null); - } - - // Now add the candidate to the list - if (fields.Count == columnOrdinal) - { - fields.Add(candidateMd); - } - else - { - // Disallow two columns using the same ordinal (even if due to mixing null and non-null columnOrdinals) - if (fields[columnOrdinal] != null) - { - throw SQL.InvalidSchemaTableOrdinals(); - } - - // Don't use insert, since it shifts all later columns down a notch - fields[columnOrdinal] = candidateMd; - } - - // Propagate key information - if (!row.IsNull(ordinalForIsKey) && (bool)row[ordinalForIsKey]) - { - keyCols[columnOrdinal] = true; - hasKey = true; - } - } - -#if DEBUG - // Check for holes - // Above loop logic prevents holes since: - // 1) loop processes fieldcount # of columns - // 2) no ordinals outside continuous range from 0 to fieldcount - 1 are allowed - // 3) no duplicate ordinals are allowed - // But assert no holes to be sure. - foreach (SmiExtendedMetaData md in fields) - { - Debug.Assert(null != md, "Shouldn't be able to have holes, since original loop algorithm prevents such."); - } -#endif - - // Add unique key property, if any defined. - if (hasKey) - { - props = new SmiMetaDataPropertyCollection(); - props[SmiPropertySelector.UniqueKey] = new SmiUniqueKeyProperty(new List(keyCols)); - } - } - } - - internal byte GetActualScale() - { - if (ShouldSerializeScale()) - { - return ScaleInternal; - } - - // issue: how could a user specify 0 as the actual scale? - if (GetMetaTypeOnly().IsVarTime) - { - return TdsEnums.DEFAULT_VARTIME_SCALE; - } - return ValueScale(CoercedValue); - } - - // - // always returns data in bytes - except for non-unicode chars, which will be in number of chars - // - internal int GetActualSize() - { - MetaType mt = InternalMetaType; - SqlDbType actualType = mt.SqlDbType; - // NOTE: Users can change the Udt at any time, so we may need to recalculate - if ((_actualSize == -1) || (actualType == SqlDbType.Udt)) - { - _actualSize = 0; - object val = GetCoercedValue(); - bool isSqlVariant = false; - - if (IsNull && !mt.IsVarTime) - { - return 0; - } - - // if this is a backend SQLVariant type, then infer the TDS type from the SQLVariant type - if (actualType == SqlDbType.Variant) - { - mt = MetaType.GetMetaTypeFromValue(val, streamAllowed: false); - actualType = MetaType.GetSqlDataType(mt.TDSType, 0 /*no user type*/, 0 /*non-nullable type*/).SqlDbType; - isSqlVariant = true; - } - - if (mt.IsFixed) - { - _actualSize = mt.FixedLength; - } - else - { - // @hack: until we have ForceOffset behavior we have the following semantics: - // @hack: if the user supplies a Size through the Size property or constructor, - // @hack: we only send a MAX of Size bytes over. If the actualSize is < Size, then - // @hack: we send over actualSize - int coercedSize = 0; - - // get the actual length of the data, in bytes - switch (actualType) - { - case SqlDbType.NChar: - case SqlDbType.NVarChar: - case SqlDbType.NText: - case SqlDbType.Xml: - { - coercedSize = ((!HasFlag(SqlParameterFlags.IsNull)) && (!HasFlag(SqlParameterFlags.CoercedValueIsDataFeed))) ? (StringSize(val, HasFlag(SqlParameterFlags.CoercedValueIsSqlType))) : 0; - _actualSize = (ShouldSerializeSize() ? Size : 0); - _actualSize = (ShouldSerializeSize() && (_actualSize <= coercedSize)) ? _actualSize : coercedSize; - if (_actualSize == -1) - { - _actualSize = coercedSize; - } - _actualSize <<= 1; - } - break; - case SqlDbType.Char: - case SqlDbType.VarChar: - case SqlDbType.Text: - { - // for these types, ActualSize is the num of chars, not actual bytes - since non-unicode chars are not always uniform size - coercedSize = ((!HasFlag(SqlParameterFlags.IsNull)) && (!HasFlag(SqlParameterFlags.CoercedValueIsDataFeed))) ? (StringSize(val, HasFlag(SqlParameterFlags.CoercedValueIsSqlType))) : 0; - _actualSize = (ShouldSerializeSize() ? Size : 0); - _actualSize = (ShouldSerializeSize() && (_actualSize <= coercedSize)) ? _actualSize : coercedSize; - if (_actualSize == -1) - { - _actualSize = coercedSize; - } - } - break; - case SqlDbType.Binary: - case SqlDbType.VarBinary: - case SqlDbType.Image: - case SqlDbType.Timestamp: - coercedSize = ((!HasFlag(SqlParameterFlags.IsNull)) && (!HasFlag(SqlParameterFlags.CoercedValueIsDataFeed))) ? (BinarySize(val, HasFlag(SqlParameterFlags.CoercedValueIsSqlType))) : 0; - _actualSize = (ShouldSerializeSize() ? Size : 0); - _actualSize = ((ShouldSerializeSize() && (_actualSize <= coercedSize)) ? _actualSize : coercedSize); - if (_actualSize == -1) - { - _actualSize = coercedSize; - } - break; - case SqlDbType.Udt: - if (!IsNull) - { - coercedSize = SerializationHelperSql9.SizeInBytes(val); - } - break; - case SqlDbType.Structured: - coercedSize = -1; - break; - case SqlDbType.Time: - _actualSize = isSqlVariant ? 5 : MetaType.GetTimeSizeFromScale(GetActualScale()); - break; - case SqlDbType.DateTime2: - // Date in number of days (3 bytes) + time - _actualSize = 3 + (isSqlVariant ? 5 : MetaType.GetTimeSizeFromScale(GetActualScale())); - break; - case SqlDbType.DateTimeOffset: - // Date in days (3 bytes) + offset in minutes (2 bytes) + time - _actualSize = 5 + (isSqlVariant ? 5 : MetaType.GetTimeSizeFromScale(GetActualScale())); - break; - default: - Debug.Fail("Unknown variable length type!"); - break; - } - - // don't even send big values over to the variant - if (isSqlVariant && (coercedSize > TdsEnums.TYPE_SIZE_LIMIT)) - { - throw SQL.ParameterInvalidVariant(ParameterName); - } - } - } - - return _actualSize; - } - - internal byte GetActualPrecision() - { - return ShouldSerializePrecision() ? PrecisionInternal : ValuePrecision(CoercedValue); - } - - internal object GetCoercedValue() - { - // NOTE: User can change the Udt at any time - if ((_coercedValue == null) || (_internalMetaType.SqlDbType == SqlDbType.Udt)) - { // will also be set during parameter Validation - bool isDataFeed = Value is DataFeed; - if (IsNull || isDataFeed) - { - // No coercion is done for DataFeeds and Nulls - _coercedValue = Value; - SetFlag(SqlParameterFlags.CoercedValueIsSqlType, _coercedValue != null && HasFlag(SqlParameterFlags.IsSqlParameterSqlType)); // set to null for output parameters that keeps _isSqlParameterSqlType - SetFlag(SqlParameterFlags.CoercedValueIsDataFeed, isDataFeed); - _actualSize = IsNull ? 0 : -1; - } - else - { - _coercedValue = CoerceValue(Value, _internalMetaType, out bool coercedValueIsDataFeed, out bool typeChanged); - SetFlag(SqlParameterFlags.CoercedValueIsDataFeed, coercedValueIsDataFeed); - SetFlag(SqlParameterFlags.CoercedValueIsSqlType, HasFlag(SqlParameterFlags.IsSqlParameterSqlType) && (!typeChanged)); // Type changed always results in a CLR type - _actualSize = -1; - } - } - AssertCachedPropertiesAreValid(); - return _coercedValue; - } - - internal int GetParameterSize() - { - return ShouldSerializeSize() ? Size : ValueSize(CoercedValue); - } - - /// - /// Get SMI Metadata to write out type_info stream. - /// - /// - internal SmiParameterMetaData GetMetadataForTypeInfo() - { - if (_internalMetaType == null) - { - _internalMetaType = GetMetaTypeOnly(); - } - - return MetaDataForSmi(out _); - } - - // IMPORTANT DEVNOTE: This method is being used for parameter encryption functionality, to get the type_info TDS object from SqlParameter. - // Please consider impact to that when changing this method. Refer to the callers of SqlParameter.GetMetadataForTypeInfo(). - internal SmiParameterMetaData MetaDataForSmi(out ParameterPeekAheadValue peekAhead) - { - peekAhead = null; - MetaType mt = ValidateTypeLengths(); - long actualLen = GetActualSize(); - long maxLen = Size; - - // GetActualSize returns bytes length, but smi expects char length for - // character types, so adjust - if (!mt.IsLong) - { - if (mt.SqlDbType == SqlDbType.NChar || mt.SqlDbType == SqlDbType.NVarChar) - { - actualLen /= sizeof(char); - } - - if (actualLen > maxLen) - { - maxLen = actualLen; - } - } - - // Determine maxLength for types that ValidateTypeLengths won't figure out - if (maxLen == 0) - { - if (mt.SqlDbType == SqlDbType.Binary || mt.SqlDbType == SqlDbType.VarBinary) - { - maxLen = SmiMetaData.MaxBinaryLength; - } - else if (mt.SqlDbType == SqlDbType.Char || mt.SqlDbType == SqlDbType.VarChar) - { - maxLen = SmiMetaData.MaxANSICharacters; - } - else if (mt.SqlDbType == SqlDbType.NChar || mt.SqlDbType == SqlDbType.NVarChar) - { - maxLen = SmiMetaData.MaxUnicodeCharacters; - } - } - else if ( - (maxLen > SmiMetaData.MaxBinaryLength && (SqlDbType.Binary == mt.SqlDbType || SqlDbType.VarBinary == mt.SqlDbType)) || - (maxLen > SmiMetaData.MaxANSICharacters && (SqlDbType.Char == mt.SqlDbType || SqlDbType.VarChar == mt.SqlDbType)) || - (maxLen > SmiMetaData.MaxUnicodeCharacters && (SqlDbType.NChar == mt.SqlDbType || SqlDbType.NVarChar == mt.SqlDbType)) - ) - { - maxLen = -1; - } - - int localeId = LocaleId; - if (localeId == 0 && mt.IsCharType) - { - if (GetCoercedValue() is SqlString sqlString && !sqlString.IsNull) - { - localeId = sqlString.LCID; - } - else - { - localeId = CultureInfo.CurrentCulture.LCID; - } - } - - SqlCompareOptions compareOpts = CompareInfo; - if (compareOpts == 0 && mt.IsCharType) - { - if (GetCoercedValue() is SqlString sqlString && !sqlString.IsNull) - { - compareOpts = sqlString.SqlCompareOptions; - } - else - { - compareOpts = SmiMetaData.GetDefaultForType(mt.SqlDbType).CompareOptions; - } - } - - string typeSpecificNamePart1 = null; - string typeSpecificNamePart2 = null; - string typeSpecificNamePart3 = null; - - if (SqlDbType.Xml == mt.SqlDbType) - { - typeSpecificNamePart1 = XmlSchemaCollectionDatabase; - typeSpecificNamePart2 = XmlSchemaCollectionOwningSchema; - typeSpecificNamePart3 = XmlSchemaCollectionName; - } - else if (SqlDbType.Udt == mt.SqlDbType || (SqlDbType.Structured == mt.SqlDbType && !string.IsNullOrEmpty(TypeName))) - { - // Split the input name. The type name is specified as single 3 part name. - // NOTE: ParseTypeName throws if format is incorrect - string[] names; - if (mt.SqlDbType == SqlDbType.Udt) - { - names = ParseTypeName(UdtTypeName, true /* is UdtTypeName */); - } - else - { - names = ParseTypeName(TypeName, false /* not UdtTypeName */); - } - - if (names.Length == 1) - { - typeSpecificNamePart3 = names[0]; - } - else if (names.Length == 2) - { - typeSpecificNamePart2 = names[0]; - typeSpecificNamePart3 = names[1]; - } - else if (names.Length == 3) - { - typeSpecificNamePart1 = names[0]; - typeSpecificNamePart2 = names[1]; - typeSpecificNamePart3 = names[2]; - } - else - { - throw ADP.ArgumentOutOfRange(nameof(names)); - } - - if ( - (!string.IsNullOrEmpty(typeSpecificNamePart1) && TdsEnums.MAX_SERVERNAME < typeSpecificNamePart1.Length) || - (!string.IsNullOrEmpty(typeSpecificNamePart2) && TdsEnums.MAX_SERVERNAME < typeSpecificNamePart2.Length) || - (!string.IsNullOrEmpty(typeSpecificNamePart3) && TdsEnums.MAX_SERVERNAME < typeSpecificNamePart3.Length) - ) - { - throw ADP.ArgumentOutOfRange(nameof(names)); - } - } - - byte precision = GetActualPrecision(); - byte scale = GetActualScale(); - - // precision for decimal types may still need adjustment. - if (mt.SqlDbType == SqlDbType.Decimal) - { - if (precision == 0) - { - precision = TdsEnums.DEFAULT_NUMERIC_PRECISION; - } - } - - // Sub-field determination - List fields = null; - SmiMetaDataPropertyCollection extendedProperties = null; - if (mt.SqlDbType == SqlDbType.Structured) - { - GetActualFieldsAndProperties(out fields, out extendedProperties, out peekAhead); - } - - return new SmiParameterMetaData( - mt.SqlDbType, - maxLen, - precision, - scale, - localeId, - compareOpts, - null, // Udt type not used for parameters - SqlDbType.Structured == mt.SqlDbType, - fields, - extendedProperties, - ParameterNameFixed, - typeSpecificNamePart1, - typeSpecificNamePart2, - typeSpecificNamePart3, - Direction - ); - } - - [Conditional("DEBUG")] - internal void AssertCachedPropertiesAreValid() - { - AssertPropertiesAreValid(_coercedValue, HasFlag(SqlParameterFlags.CoercedValueIsSqlType), HasFlag(SqlParameterFlags.CoercedValueIsDataFeed), IsNull); - } - - [Conditional("DEBUG")] - internal void AssertPropertiesAreValid(object value, bool? isSqlType = null, bool? isDataFeed = null, bool? isNull = null) - { - Debug.Assert(!isSqlType.HasValue || (isSqlType.Value == (value is INullable)), "isSqlType is incorrect"); - Debug.Assert(!isDataFeed.HasValue || (isDataFeed.Value == (value is DataFeed)), "isDataFeed is incorrect"); - Debug.Assert(!isNull.HasValue || (isNull.Value == ADP.IsNull(value)), "isNull is incorrect"); - } - - private SqlDbType GetMetaSqlDbTypeOnly() - { - MetaType metaType = _metaType; - if (null == metaType) - { // infer the type from the value - metaType = MetaType.GetDefaultMetaType(); - } - return metaType.SqlDbType; - } - - // This may not be a good thing to do in case someone overloads the parameter type but I - // don't want to go from SqlDbType -> metaType -> TDSType - private MetaType GetMetaTypeOnly() - { - if (_metaType != null) - { - return _metaType; - } - if (null != _value && DBNull.Value != _value) - { - // We have a value set by the user then just use that value - // char and char[] are not directly supported so we convert those values to string - Type valueType = _value.GetType(); - if (valueType == typeof(char)) - { - _value = _value.ToString(); - valueType = typeof(string); - } - else if (valueType == typeof(char[])) - { - _value = new string((char[])_value); - valueType = typeof(string); - } - return MetaType.GetMetaTypeFromType(valueType); - } - else if (_sqlBufferReturnValue != null) - { // value came back from the server - Type valueType = _sqlBufferReturnValue.GetTypeFromStorageType(HasFlag(SqlParameterFlags.IsSqlParameterSqlType)); - if (valueType != null) - { - return MetaType.GetMetaTypeFromType(valueType); - } - } - return MetaType.GetDefaultMetaType(); - } - - internal void Prepare(SqlCommand cmd) - { - if (_metaType == null) - { - throw ADP.PrepareParameterType(cmd); - } - else if (!ShouldSerializeSize() && !_metaType.IsFixed) - { - throw ADP.PrepareParameterSize(cmd); - } - else if ((!ShouldSerializePrecision() && !ShouldSerializeScale()) && (_metaType.SqlDbType == SqlDbType.Decimal)) - { - throw ADP.PrepareParameterScale(cmd, SqlDbType.ToString()); - } - } - - private void PropertyChanging() - { - _internalMetaType = null; - } - - private void PropertyTypeChanging() - { - PropertyChanging(); - CoercedValue = null; - } - - internal void ResetParent() => _parent = null; - - internal void SetSqlBuffer(SqlBuffer buff) - { - _sqlBufferReturnValue = buff; - _value = null; - _coercedValue = null; - SetFlag(SqlParameterFlags.IsNull, _sqlBufferReturnValue.IsNull); - SetFlag(SqlParameterFlags.CoercedValueIsDataFeed, false); - SetFlag(SqlParameterFlags.CoercedValueIsSqlType, false); - _udtLoadError = null; - _actualSize = -1; - } - - private void SetFlag(SqlParameterFlags flag, bool value) - { - _flags = value ? _flags | flag : _flags & ~flag; - } - - internal void SetUdtLoadError(Exception e) - { - _udtLoadError = e; - } - - internal void Validate(int index, bool isCommandProc) - { - MetaType metaType = GetMetaTypeOnly(); - _internalMetaType = metaType; - - // SqlParameter does a Size Validation check and would fail if the size is 0. - // This condition filters all scenarios where we view a valid size 0. - if ( - ADP.IsDirection(this, ParameterDirection.Output) && - !ADP.IsDirection(this, ParameterDirection.ReturnValue) && - (!metaType.IsFixed) && - !ShouldSerializeSize() && - ((null == _value) || Convert.IsDBNull(_value)) && - (SqlDbType != SqlDbType.Timestamp) && - (SqlDbType != SqlDbType.Udt) && - (SqlDbType != SqlDbType.Xml) && - !metaType.IsVarTime - ) - { - throw ADP.UninitializedParameterSize(index, metaType.ClassType); - } - - if (metaType.SqlDbType != SqlDbType.Udt && Direction != ParameterDirection.Output) - { - GetCoercedValue(); - } - - //check if the UdtTypeName is specified for Udt params - if (metaType.SqlDbType == SqlDbType.Udt) - { - if (string.IsNullOrEmpty(UdtTypeName)) - { - throw SQL.MustSetUdtTypeNameForUdtParams(); - } - } - else if (!string.IsNullOrEmpty(UdtTypeName)) - { - throw SQL.UnexpectedUdtTypeNameForNonUdtParams(); - } - - // Validate structured-type-specific details. - if (metaType.SqlDbType == SqlDbType.Structured) - { - if (!isCommandProc && string.IsNullOrEmpty(TypeName)) - { - throw SQL.MustSetTypeNameForParam(metaType.TypeName, ParameterName); - } - - if (Direction != ParameterDirection.Input) - { - throw SQL.UnsupportedTVPOutputParameter(Direction, ParameterName); - } - - if (GetCoercedValue() == DBNull.Value) - { - throw SQL.DBNullNotSupportedForTVPValues(ParameterName); - } - } - else if (!string.IsNullOrEmpty(TypeName)) - { - throw SQL.UnexpectedTypeNameForNonStructParams(ParameterName); - } - } - - // func will change type to that with a 4 byte length if the type has a two - // byte length and a parameter length > than that expressible in 2 bytes - internal MetaType ValidateTypeLengths() - { - MetaType mt = InternalMetaType; - // Since the server will automatically reject any - // char, varchar, binary, varbinary, nchar, or nvarchar parameter that has a - // byte sizeInCharacters > 8000 bytes, we promote the parameter to image, text, or ntext. This - // allows the user to specify a parameter type using a COM+ datatype and be able to - // use that parameter against a BLOB column. - if ((mt.SqlDbType != SqlDbType.Udt) && !mt.IsFixed && !mt.IsLong) - { // if type has 2 byte length - long actualSizeInBytes = GetActualSize(); - long sizeInCharacters = Size; - - long maxSizeInBytes; - if (mt.IsNCharType) - { - maxSizeInBytes = ((sizeInCharacters * sizeof(char)) > actualSizeInBytes) ? sizeInCharacters * sizeof(char) : actualSizeInBytes; - } - else - { - // Notes: - // Elevation from (n)(var)char (4001+) to (n)text succeeds without failure only with Yukon and greater. - // it fails in sql server 2000 - maxSizeInBytes = (sizeInCharacters > actualSizeInBytes) ? sizeInCharacters : actualSizeInBytes; - } - - if ( - (maxSizeInBytes > TdsEnums.TYPE_SIZE_LIMIT) || - HasFlag(SqlParameterFlags.CoercedValueIsDataFeed) || - (sizeInCharacters == -1) || - (actualSizeInBytes == -1) - ) - { // is size > size able to be described by 2 bytes - // Convert the parameter to its max type - mt = MetaType.GetMaxMetaTypeFromMetaType(mt); - _metaType = mt; - InternalMetaType = mt; - if (!mt.IsPlp) - { - if (mt.SqlDbType == SqlDbType.Xml) - { - throw ADP.InvalidMetaDataValue(); //Xml should always have IsPartialLength = true - } - if ( - mt.SqlDbType == SqlDbType.NVarChar || - mt.SqlDbType == SqlDbType.VarChar || - mt.SqlDbType == SqlDbType.VarBinary - ) - { - Size = (int)SmiMetaData.UnlimitedMaxLengthIndicator; - } - } - } - } - return mt; - } - - private byte ValuePrecision(object value) - { - if (value is SqlDecimal sqlDecimal) - { - if (sqlDecimal.IsNull) - { - return 0; - } - return sqlDecimal.Precision; - } - return ValuePrecisionCore(value); - } - - private byte ValueScale(object value) - { - if (value is SqlDecimal sqlDecimal) - { - if (sqlDecimal.IsNull) - { - return 0; - } - return sqlDecimal.Scale; - } - return ValueScaleCore(value); - } - - private int ValueSize(object value) - { - if (value is SqlString sqlString) - { - if (sqlString.IsNull) - { - return 0; - } - return sqlString.Value.Length; - } - if (value is SqlChars sqlChars) - { - if (sqlChars.IsNull) - { - return 0; - } - return sqlChars.Value.Length; - } - - if (value is SqlBinary sqlBinary) - { - if (sqlBinary.IsNull) - { - return 0; - } - return sqlBinary.Length; - } - if (value is SqlBytes sqlBytes) - { - if (sqlBytes.IsNull) - { - return 0; - } - return (int)(sqlBytes.Length); - } - if (value is DataFeed) - { - // Unknown length - return 0; - } - return ValueSizeCore(value); - } - - private byte ValuePrecisionCore(object value) - { - if (value is decimal decimalValue) - { - return ((SqlDecimal)decimalValue).Precision; - } - return 0; - } - - private byte ValueScaleCore(object value) - { - if (value is decimal decimalValue) - { - return (byte)((decimal.GetBits(decimalValue)[3] & 0x00ff0000) >> 0x10); - } - return 0; - } - - private int ValueSizeCore(object value) - { - if (!ADP.IsNull(value)) - { - switch (value) - { - case string svalue: - return svalue.Length; - case byte[] bvalue: - return bvalue.Length; - case char[] cvalue: - return cvalue.Length; - case byte _: - case char _: - return 1; - } - } - return 0; - } - - // Coerced Value is also used in SqlBulkCopy.ConvertValue(object value, _SqlMetaData metadata) - internal static object CoerceValue(object value, MetaType destinationType, out bool coercedToDataFeed, out bool typeChanged, bool allowStreaming = true) - { - Debug.Assert(!(value is DataFeed), "Value provided should not already be a data feed"); - Debug.Assert(!ADP.IsNull(value), "Value provided should not be null"); - Debug.Assert(null != destinationType, "null destinationType"); - - coercedToDataFeed = false; - typeChanged = false; - Type currentType = value.GetType(); - - if ( - (destinationType.ClassType != typeof(object)) && - (destinationType.ClassType != currentType) && - ( - (destinationType.SqlType != currentType) || - (destinationType.SqlDbType == SqlDbType.Xml) - ) - ) - { // Special case for Xml types (since we need to convert SqlXml into a string) - try - { - // Assume that the type changed - typeChanged = true; - if (destinationType.ClassType == typeof(string)) - { - // For Xml data, destination Type is always string - if (currentType == typeof(SqlXml)) - { - value = MetaType.GetStringFromXml((XmlReader)(((SqlXml)value).CreateReader())); - } - else if (currentType == typeof(SqlString)) - { - typeChanged = false; // Do nothing - } - else if (typeof(XmlReader).IsAssignableFrom(currentType)) - { - if (allowStreaming) - { - coercedToDataFeed = true; - value = new XmlDataFeed((XmlReader)value); - } - else - { - value = MetaType.GetStringFromXml((XmlReader)value); - } - } - else if (currentType == typeof(char[])) - { - value = new string((char[])value); - } - else if (currentType == typeof(SqlChars)) - { - value = new string(((SqlChars)value).Value); - } - else if (value is TextReader textReader && allowStreaming) - { - coercedToDataFeed = true; - value = new TextDataFeed(textReader); - } - else - { - value = Convert.ChangeType(value, destinationType.ClassType, null); - } - } - else if ((destinationType.DbType == DbType.Currency) && (currentType == typeof(string))) - { - value = decimal.Parse((string)value, NumberStyles.Currency, null); - } - else if ((currentType == typeof(SqlBytes)) && (destinationType.ClassType == typeof(byte[]))) - { - typeChanged = false; // Do nothing - } - else if ((currentType == typeof(string)) && (destinationType.SqlDbType == SqlDbType.Time)) - { - value = TimeSpan.Parse((string)value); - } - else if ((currentType == typeof(string)) && (destinationType.SqlDbType == SqlDbType.DateTimeOffset)) - { - value = DateTimeOffset.Parse((string)value, (IFormatProvider)null); - } - else if ((currentType == typeof(DateTime)) && (destinationType.SqlDbType == SqlDbType.DateTimeOffset)) - { - value = new DateTimeOffset((DateTime)value); - } - else if ( - TdsEnums.SQLTABLE == destinationType.TDSType && - ( - value is DataTable || - value is DbDataReader || - value is IEnumerable - ) - ) - { - // no conversion for TVPs. - typeChanged = false; - } - else if (destinationType.ClassType == typeof(byte[]) && allowStreaming && value is Stream stream) - { - coercedToDataFeed = true; - value = new StreamDataFeed(stream); - } - else - { - value = Convert.ChangeType(value, destinationType.ClassType, null); - } - } - catch (Exception e) - { - if (!ADP.IsCatchableExceptionType(e)) - { - throw; - } - - throw ADP.ParameterConversionFailed(value, destinationType.ClassType, e); - } - } - - Debug.Assert(allowStreaming || !coercedToDataFeed, "Streaming is not allowed, but type was coerced into a data feed"); - Debug.Assert(value.GetType() == currentType ^ typeChanged, "Incorrect value for typeChanged"); - return value; - } - - private static int StringSize(object value, bool isSqlType) - { - if (isSqlType) - { - Debug.Assert(!((INullable)value).IsNull, "Should not call StringSize on null values"); - if (value is SqlString sqlString) - { - return sqlString.Value.Length; - } - if (value is SqlChars sqlChars) - { - return sqlChars.Value.Length; - } - } - else - { - if (value is string svalue) - { - return svalue.Length; - } - if (value is char[] cvalue) - { - return cvalue.Length; - } - if (value is char) - { - return 1; - } - } - - // Didn't match, unknown size - return 0; - } - - private static int BinarySize(object value, bool isSqlType) - { - if (isSqlType) - { - Debug.Assert(!((INullable)value).IsNull, "Should not call StringSize on null values"); - if (value is SqlBinary sqlBinary) - { - return sqlBinary.Length; - } - if (value is SqlBytes sqlBytes) - { - return sqlBytes.Value.Length; - } - } - else - { - if (value is byte[] bvalue) - { - return bvalue.Length; - } - if (value is byte) - { - return 1; - } - } - - // Didn't match, unknown size - return 0; - } - - // parse an string of the form db.schema.name where any of the three components - // might have "[" "]" and dots within it. - // returns: - // [0] dbname (or null) - // [1] schema (or null) - // [2] name - // NOTE: if perf/space implications of Regex is not a problem, we can get rid - // of this and use a simple regex to do the parsing - internal static string[] ParseTypeName(string typeName, bool isUdtTypeName) - { - Debug.Assert(null != typeName, "null typename passed to ParseTypeName"); - - try - { - string errorMsg = isUdtTypeName ? Strings.SQL_UDTTypeName : Strings.SQL_TypeName; - return MultipartIdentifier.ParseMultipartIdentifier(typeName, "[\"", "]\"", '.', 3, true, errorMsg, true); - } - catch (ArgumentException) - { - if (isUdtTypeName) - { - throw SQL.InvalidUdt3PartNameFormat(); - } - else - { - throw SQL.InvalidParameterTypeNameFormat(); - } - } - } - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.Designer.cs b/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.Designer.cs index f33751fb08..0629ceb1ac 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.Designer.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.Designer.cs @@ -942,6 +942,24 @@ internal static string Data_InvalidOffsetLength { } } + /// + /// Looks up a localized string similar to Update. + /// + internal static string DataCategory_Update { + get { + return ResourceManager.GetString("DataCategory_Update", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to XML. + /// + internal static string DataCategory_Xml { + get { + return ResourceManager.GetString("DataCategory_Xml", resourceCulture); + } + } + /// /// Looks up a localized string similar to Internal error occurred when retrying the download of the HGS root certificate after the initial request failed. Contact Customer Support Services.. /// diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.resx b/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.resx index bfe5559389..6be833f7ee 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.resx +++ b/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.resx @@ -1932,4 +1932,10 @@ Parameter '{0}' cannot have Direction Output or InputOutput when EnableOptimizedParameterBinding is enabled on the parent command. + + Update + + + XML + \ No newline at end of file diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Resources/StringsHelper.cs b/src/Microsoft.Data.SqlClient/netcore/src/Resources/StringsHelper.cs index a2ee7e51d2..5e283d5e9e 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Resources/StringsHelper.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Resources/StringsHelper.cs @@ -76,6 +76,7 @@ internal class ResourceNames { internal const string DataCategory_Data = @"Data"; internal const string DataCategory_Update = @"Update"; + internal const string DataCategory_Xml = @"XML"; internal const string DbCommand_CommandTimeout = @"Time to wait for command to execute."; internal const string DbConnection_State = @"The ConnectionState indicating whether the connection is open or closed."; internal const string DataCategory_Fill = @"Fill"; diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj index 1fb9b7e0a3..876a2e64ee 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -515,7 +515,9 @@ - + + Microsoft\Data\SqlClient\SqlParameter.cs + diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlParameter.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs similarity index 91% rename from src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlParameter.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs index 6e0290f991..50de8c0767 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlParameter.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs @@ -16,6 +16,8 @@ using System.Xml; using Microsoft.Data.Common; using Microsoft.Data.SqlClient.Server; +using System.Text; +using System.Threading; namespace Microsoft.Data.SqlClient { @@ -35,25 +37,36 @@ internal StreamDataFeed(Stream source) internal class TextDataFeed : DataFeed { + private static UnicodeEncoding s_defaultEncoding; internal TextReader _source; internal TextDataFeed(TextReader source) { _source = source; } + internal static UnicodeEncoding DefaultEncoding + { + get + { + UnicodeEncoding encoding = s_defaultEncoding; + if (encoding is null) + { + encoding = new UnicodeEncoding(false, false); + encoding = Interlocked.CompareExchange(ref s_defaultEncoding, encoding, null) ?? encoding; + } + return encoding; + } + } } internal class XmlDataFeed : DataFeed { internal XmlReader _source; - internal XmlDataFeed(XmlReader source) - { - _source = source; - } + internal XmlDataFeed(XmlReader source) => _source = source; } - /// + /// [TypeConverter(typeof(SqlParameter.SqlParameterConverter))] public sealed partial class SqlParameter : DbParameter, IDbDataParameter, ICloneable { @@ -230,7 +243,7 @@ private enum SqlParameterFlags : ushort private DataRowVersion _sourceVersion; private SqlParameterFlags _flags; - /// + /// public SqlParameter() : base() { _flags = SqlParameterFlags.IsNull; @@ -238,14 +251,14 @@ public SqlParameter() : base() _direction = ParameterDirection.Input; } - /// + /// public SqlParameter(string parameterName, SqlDbType dbType) : this() { ParameterName = parameterName; SqlDbType = dbType; } - /// + /// public SqlParameter(string parameterName, object value) : this() { Debug.Assert(!(value is SqlDbType), "use SqlParameter(string, SqlDbType)"); @@ -254,7 +267,7 @@ public SqlParameter(string parameterName, object value) : this() Value = value; } - /// + /// public SqlParameter(string parameterName, SqlDbType dbType, int size) : this() { ParameterName = parameterName; @@ -262,7 +275,7 @@ public SqlParameter(string parameterName, SqlDbType dbType, int size) : this() Size = size; } - /// + /// public SqlParameter(string parameterName, SqlDbType dbType, int size, string sourceColumn) : this() { ParameterName = parameterName; @@ -271,7 +284,7 @@ public SqlParameter(string parameterName, SqlDbType dbType, int size, string sou SourceColumn = sourceColumn; } - /// + /// [EditorBrowsable(EditorBrowsableState.Advanced)] public SqlParameter( string parameterName, @@ -289,13 +302,13 @@ object value { Direction = direction; IsNullable = isNullable; - PrecisionInternal = precision; - ScaleInternal = scale; + Precision = precision; + Scale = scale; SourceVersion = sourceVersion; Value = value; } - /// + /// public SqlParameter( string parameterName, SqlDbType dbType, @@ -317,8 +330,8 @@ string xmlSchemaCollectionName SqlDbType = dbType; Size = size; Direction = direction; - PrecisionInternal = precision; - ScaleInternal = scale; + Precision = precision; + Scale = scale; SourceColumn = sourceColumn; SourceVersion = sourceVersion; SourceColumnNullMapping = sourceColumnNullMapping; @@ -364,7 +377,7 @@ internal bool HasReceivedMetadata /// internal byte NormalizationRuleVersion => CipherMetadata?.NormalizationRuleVersion ?? 0x00; - /// + /// [Browsable(false)] public SqlCompareOptions CompareInfo { @@ -400,34 +413,34 @@ public SqlCompareOptions CompareInfo } } - /// - [ResCategory("XML")] + /// + [ResCategory(StringsHelper.ResourceNames.DataCategory_Xml)] public string XmlSchemaCollectionDatabase { get => _xmlSchemaCollection?.Database ?? string.Empty; set => EnsureXmlSchemaCollection().Database = value; } - /// - [ResCategory("XML")] + /// + [ResCategory(StringsHelper.ResourceNames.DataCategory_Xml)] public string XmlSchemaCollectionOwningSchema { get => _xmlSchemaCollection?.OwningSchema ?? string.Empty; set => EnsureXmlSchemaCollection().OwningSchema = value; } - /// - [ResCategory("XML")] + /// + [ResCategory(StringsHelper.ResourceNames.DataCategory_Xml)] public string XmlSchemaCollectionName { get => _xmlSchemaCollection?.Name ?? string.Empty; set => EnsureXmlSchemaCollection().Name = value; } - /// + /// [ DefaultValue(false), - ResCategory("Data") + ResCategory(StringsHelper.ResourceNames.DataCategory_Data) ] public bool ForceColumnEncryption { @@ -435,7 +448,7 @@ public bool ForceColumnEncryption set => SetFlag(SqlParameterFlags.ForceColumnEncryption, value); } - /// + /// public override DbType DbType { get => GetMetaTypeOnly().DbType; @@ -450,11 +463,11 @@ public override DbType DbType } } - /// + /// public override void ResetDbType() => ResetSqlDbType(); - /// - [ResCategory("Data")] + /// + [ResCategory(StringsHelper.ResourceNames.DataCategory_Data)] public override string ParameterName { get => _parameterName ?? string.Empty; @@ -482,7 +495,7 @@ public override string ParameterName } } - /// + /// [Browsable(false)] public int LocaleId { @@ -512,7 +525,7 @@ public int LocaleId } } - /// + /// [ DefaultValue((byte)0), ResCategory(StringsHelper.ResourceNames.DataCategory_Data) @@ -525,7 +538,7 @@ public int LocaleId private bool ShouldSerializePrecision() => _precision != 0; - /// + /// [ DefaultValue((byte)0), ResCategory(StringsHelper.ResourceNames.DataCategory_Data) @@ -562,10 +575,10 @@ internal byte ScaleInternal private bool ShouldSerializeScale() => _scale != 0; // V1.0 compat, ignore _hasScale - /// + /// [ RefreshProperties(RefreshProperties.All), - ResCategory("Data"), + ResCategory(StringsHelper.ResourceNames.DataCategory_Data), DbProviderSpecificTypeProperty(true) ] public SqlDbType SqlDbType @@ -595,7 +608,7 @@ public SqlDbType SqlDbType private bool ShouldSerializeSqlDbType() => _metaType != null; - /// + /// public void ResetSqlDbType() { if (_metaType != null) @@ -605,7 +618,7 @@ public void ResetSqlDbType() } } - /// + /// [ Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), @@ -656,7 +669,7 @@ public object SqlValue } } - /// + /// [ Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced) @@ -667,7 +680,7 @@ public string UdtTypeName set => _udtTypeName = value; } - /// + /// [ Browsable(false), EditorBrowsable(EditorBrowsableState.Advanced) @@ -682,10 +695,10 @@ public string TypeName } } - /// + /// [ RefreshProperties(RefreshProperties.All), - ResCategory("Data"), + ResCategory(StringsHelper.ResourceNames.DataCategory_Data), TypeConverter(typeof(StringConverter)), ] public override object Value @@ -724,10 +737,10 @@ public override object Value } } - /// + /// [ RefreshProperties(RefreshProperties.All), - ResCategory("Data"), + ResCategory(StringsHelper.ResourceNames.DataCategory_Data), ] public override ParameterDirection Direction { @@ -752,14 +765,14 @@ public override ParameterDirection Direction } } - /// + /// public override bool IsNullable { get => HasFlag(SqlParameterFlags.IsNullable); set => SetFlag(SqlParameterFlags.IsNullable, value); } - /// + /// public int Offset { get => _offset; @@ -773,8 +786,8 @@ public int Offset } } - /// - [ResCategory("Data")] + /// + [ResCategory(StringsHelper.ResourceNames.DataCategory_Data)] public override int Size { get @@ -811,25 +824,25 @@ private void ResetSize() private bool ShouldSerializeSize() => _size != 0; - /// - [ResCategory("Update")] + /// + [ResCategory(StringsHelper.ResourceNames.DataCategory_Update)] public override string SourceColumn { get => _sourceColumn ?? string.Empty; set => _sourceColumn = value; } - /// + /// public override bool SourceColumnNullMapping { get => HasFlag(SqlParameterFlags.SourceColumnNullMapping); set => SetFlag(SqlParameterFlags.SourceColumnNullMapping, value); } - /// + /// public override string ToString() => ParameterName; - /// + /// [ResCategory(StringsHelper.ResourceNames.DataCategory_Update)] public override DataRowVersion SourceVersion { @@ -855,7 +868,7 @@ public override DataRowVersion SourceVersion } - /// + /// object ICloneable.Clone() => new SqlParameter(this); @@ -1492,7 +1505,7 @@ internal int GetActualSize() case SqlDbType.NText: case SqlDbType.Xml: { - coercedSize = ((!HasFlag(SqlParameterFlags.IsNull)) && (!HasFlag(SqlParameterFlags.CoercedValueIsDataFeed))) ? (StringSize(val, HasFlag(SqlParameterFlags.CoercedValueIsSqlType))) : 0; + coercedSize = ((!HasFlag(SqlParameterFlags.IsNull)) && (!HasFlag(SqlParameterFlags.CoercedValueIsDataFeed))) ? StringSize(val, HasFlag(SqlParameterFlags.CoercedValueIsSqlType)) : 0; _actualSize = (ShouldSerializeSize() ? Size : 0); _actualSize = (ShouldSerializeSize() && (_actualSize <= coercedSize)) ? _actualSize : coercedSize; if (_actualSize == -1) @@ -1531,8 +1544,12 @@ internal int GetActualSize() case SqlDbType.Udt: if (!IsNull) { +#if NETFRAMEWORK //call the static function coercedSize = AssemblyCache.GetLength(val); +#else + coercedSize = SerializationHelperSql9.SizeInBytes(val); +#endif } break; case SqlDbType.Structured: @@ -1620,7 +1637,11 @@ internal SmiParameterMetaData GetMetadataForTypeInfo() internal SmiParameterMetaData MetaDataForSmi(out ParameterPeekAheadValue peekAhead) { peekAhead = null; - MetaType mt = ValidateTypeLengths(true /* Yukon or newer */ ); + MetaType mt = ValidateTypeLengths( +#if NETFRAMEWORK + true /* Yukon or newer */ +#endif + ); long actualLen = GetActualSize(); long maxLen = Size; @@ -1860,10 +1881,7 @@ internal void Prepare(SqlCommand cmd) } } - private void PropertyChanging() - { - _internalMetaType = null; - } + private void PropertyChanging() => _internalMetaType = null; private void PropertyTypeChanging() { @@ -1890,10 +1908,7 @@ internal void SetSqlBuffer(SqlBuffer buff) _actualSize = -1; } - internal void SetUdtLoadError(Exception e) - { - _udtLoadError = e; - } + internal void SetUdtLoadError(Exception e) => _udtLoadError = e; internal void Validate(int index, bool isCommandProc) { @@ -1963,7 +1978,11 @@ internal void Validate(int index, bool isCommandProc) // func will change type to that with a 4 byte length if the type has a two // byte length and a parameter length > than that expressible in 2 bytes - internal MetaType ValidateTypeLengths(bool yukonOrNewer) + internal MetaType ValidateTypeLengths( +#if NETFRAMEWORK + bool yukonOrNewer +#endif + ) { MetaType mt = InternalMetaType; // Since the server will automatically reject any @@ -1995,7 +2014,11 @@ internal MetaType ValidateTypeLengths(bool yukonOrNewer) // Keeping these goals in mind - the following are the changes we are making long maxSizeInBytes; - if (mt.IsNCharType && yukonOrNewer) + if (mt.IsNCharType +#if NETFRAMEWORK + && yukonOrNewer +#endif + ) { maxSizeInBytes = ((sizeInCharacters * sizeof(char)) > actualSizeInBytes) ? sizeInCharacters * sizeof(char) : actualSizeInBytes; } @@ -2013,7 +2036,9 @@ internal MetaType ValidateTypeLengths(bool yukonOrNewer) (sizeInCharacters == -1) || (actualSizeInBytes == -1) ) - { // is size > size able to be described by 2 bytes + { +#if NETFRAMEWORK + // is size > size able to be described by 2 bytes if (yukonOrNewer) { // Convert the parameter to its max type @@ -2063,6 +2088,27 @@ internal MetaType ValidateTypeLengths(bool yukonOrNewer) break; } } +#else + mt = MetaType.GetMaxMetaTypeFromMetaType(mt); + _metaType = mt; + InternalMetaType = mt; + if (!mt.IsPlp) + { + if (mt.SqlDbType == SqlDbType.Xml) + { + throw ADP.InvalidMetaDataValue(); //Xml should always have IsPartialLength = true + } + if ( + mt.SqlDbType == SqlDbType.NVarChar || + mt.SqlDbType == SqlDbType.VarChar || + mt.SqlDbType == SqlDbType.VarBinary + ) + { + Size = (int)SmiMetaData.UnlimitedMaxLengthIndicator; + } + } + +#endif } } return mt; From 7aebf45737714e5fa2b1e8e7d3193b78f0d27da3 Mon Sep 17 00:00:00 2001 From: Kaur-Parminder Date: Mon, 7 Mar 2022 09:49:11 -0800 Subject: [PATCH 2/7] SNI Update SNI Update --- tools/props/Versions.props | 6 +++--- tools/specs/Microsoft.Data.SqlClient.nuspec | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/props/Versions.props b/tools/props/Versions.props index 44002cbbae..d58b93e218 100644 --- a/tools/props/Versions.props +++ b/tools/props/Versions.props @@ -6,7 +6,7 @@ 5.0.0.0 - 5.0.0-dev + 5.0.0-preview1.22062.1 $(NugetPackageVersion) @@ -20,7 +20,7 @@ - 4.0.0 + 5.0.0-preview1.22062.1 4.3.1 4.3.0 @@ -38,7 +38,7 @@ 5.0.0 - 4.0.0 + 5.0.0-preview1.22062.1 5.0.0 5.0.0 5.0.0 diff --git a/tools/specs/Microsoft.Data.SqlClient.nuspec b/tools/specs/Microsoft.Data.SqlClient.nuspec index 750ee2f48a..7f5ed91f43 100644 --- a/tools/specs/Microsoft.Data.SqlClient.nuspec +++ b/tools/specs/Microsoft.Data.SqlClient.nuspec @@ -28,7 +28,7 @@ When using NuGet 3.x this package requires at least version 3.4. sqlclient microsoft.data.sqlclient - + @@ -42,7 +42,7 @@ When using NuGet 3.x this package requires at least version 3.4. - + @@ -60,7 +60,7 @@ When using NuGet 3.x this package requires at least version 3.4. - + @@ -78,7 +78,7 @@ When using NuGet 3.x this package requires at least version 3.4. - + From e7931b534e06d5eae68421c3eb5d7e52ee19d6e0 Mon Sep 17 00:00:00 2001 From: Kaur-Parminder Date: Mon, 7 Mar 2022 10:11:45 -0800 Subject: [PATCH 3/7] Revert "SNI Update" This reverts commit 7aebf45737714e5fa2b1e8e7d3193b78f0d27da3. --- tools/props/Versions.props | 6 +++--- tools/specs/Microsoft.Data.SqlClient.nuspec | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/props/Versions.props b/tools/props/Versions.props index d58b93e218..44002cbbae 100644 --- a/tools/props/Versions.props +++ b/tools/props/Versions.props @@ -6,7 +6,7 @@ 5.0.0.0 - 5.0.0-preview1.22062.1 + 5.0.0-dev $(NugetPackageVersion) @@ -20,7 +20,7 @@ - 5.0.0-preview1.22062.1 + 4.0.0 4.3.1 4.3.0 @@ -38,7 +38,7 @@ 5.0.0 - 5.0.0-preview1.22062.1 + 4.0.0 5.0.0 5.0.0 5.0.0 diff --git a/tools/specs/Microsoft.Data.SqlClient.nuspec b/tools/specs/Microsoft.Data.SqlClient.nuspec index 7f5ed91f43..750ee2f48a 100644 --- a/tools/specs/Microsoft.Data.SqlClient.nuspec +++ b/tools/specs/Microsoft.Data.SqlClient.nuspec @@ -28,7 +28,7 @@ When using NuGet 3.x this package requires at least version 3.4. sqlclient microsoft.data.sqlclient - + @@ -42,7 +42,7 @@ When using NuGet 3.x this package requires at least version 3.4. - + @@ -60,7 +60,7 @@ When using NuGet 3.x this package requires at least version 3.4. - + @@ -78,7 +78,7 @@ When using NuGet 3.x this package requires at least version 3.4. - + From 8113239af7dff0a04f2d63f025513352b54c5665 Mon Sep 17 00:00:00 2001 From: Kaur-Parminder Date: Tue, 5 Apr 2022 17:03:29 -0700 Subject: [PATCH 4/7] review comments --- .../Microsoft/Data/SqlClient/SqlParameter.cs | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs index 50de8c0767..8d8e1dc4b0 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs @@ -302,8 +302,13 @@ object value { Direction = direction; IsNullable = isNullable; +#if NETFRAMEWORK + PrecisionInternal = precision; + ScaleInternal = scale; +#else Precision = precision; Scale = scale; +#endif SourceVersion = sourceVersion; Value = value; } @@ -330,8 +335,13 @@ string xmlSchemaCollectionName SqlDbType = dbType; Size = size; Direction = direction; +#if NETFRAMEWORK + PrecisionInternal = precision; + ScaleInternal = scale; +#else Precision = precision; Scale = scale; +#endif SourceColumn = sourceColumn; SourceVersion = sourceVersion; SourceColumnNullMapping = sourceColumnNullMapping; @@ -832,7 +842,11 @@ public override string SourceColumn set => _sourceColumn = value; } - /// + /// + [ResCategory("DataCategory_Update")] +#if !NETFRAMEWORK + [ResDescription(StringsHelper.ResourceNames.SqlParameter_SourceColumnNullMapping)] +#endif public override bool SourceColumnNullMapping { get => HasFlag(SqlParameterFlags.SourceColumnNullMapping); @@ -840,6 +854,7 @@ public override bool SourceColumnNullMapping } /// + [ResCategory("Data")] public override string ToString() => ParameterName; /// @@ -1247,11 +1262,7 @@ private void GetActualFieldsAndProperties(out List fields, hasDefault = true; } - PropertyInfo serverTypeNameProperty = colMeta.GetType().GetProperty("SortOrder", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - MethodInfo getter = serverTypeNameProperty.GetGetMethod(nonPublic: true); - SortOrder sortOrder = (SortOrder)getter.Invoke(colMeta, null); - - sort[i].Order = sortOrder; + sort[i].Order = colMeta.SortOrder; if (SortOrder.Unspecified != sortOrder) { // SqlMetaData takes care of checking for negative sort ordinals with specified sort order From 4f6b82c1cb8132c81df3e7a476a24376b9f3911c Mon Sep 17 00:00:00 2001 From: Kaur-Parminder Date: Tue, 5 Apr 2022 17:07:34 -0700 Subject: [PATCH 5/7] call colMeta.SortOrder --- .../src/Microsoft/Data/SqlClient/SqlParameter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs index 8d8e1dc4b0..f5cccfa490 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs @@ -1263,7 +1263,7 @@ private void GetActualFieldsAndProperties(out List fields, } sort[i].Order = colMeta.SortOrder; - if (SortOrder.Unspecified != sortOrder) + if (SortOrder.Unspecified != colMeta.SortOrder) { // SqlMetaData takes care of checking for negative sort ordinals with specified sort order From 88e8b9285243fb98aded3d90e96f279bad9a45df Mon Sep 17 00:00:00 2001 From: David Engel Date: Fri, 27 May 2022 10:34:03 -0700 Subject: [PATCH 6/7] Remove old SQL 2005 code --- .../Microsoft/Data/SqlClient/SqlCommand.cs | 7 +- .../Microsoft/Data/SqlClient/SqlParameter.cs | 74 +------------------ 2 files changed, 6 insertions(+), 75 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs index 89a56464be..cdb492fbb0 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs @@ -6527,7 +6527,6 @@ private void SetUpRPCParameters(_SqlRPC rpc, int startCount, bool inSchema, SqlP int paramCount = GetParameterCount(parameters); int j = startCount; TdsParser parser = _activeConnection.Parser; - bool is2005OrNewer = parser.Is2005OrNewer; for (ii = 0; ii < paramCount; ii++) { @@ -6536,7 +6535,7 @@ private void SetUpRPCParameters(_SqlRPC rpc, int startCount, bool inSchema, SqlP // func will change type to that with a 4 byte length if the type has a two // byte length and a parameter length > than that expressable in 2 bytes - if ((!parameter.ValidateTypeLengths(is2005OrNewer).IsPlp) && (parameter.Direction != ParameterDirection.Output)) + if ((!parameter.ValidateTypeLengths().IsPlp) && (parameter.Direction != ParameterDirection.Output)) { parameter.FixStreamDataForNonPLP(); } @@ -6912,8 +6911,6 @@ internal string BuildParamList(TdsParser parser, SqlParameterCollection paramete StringBuilder paramList = new StringBuilder(); bool fAddSeparator = false; - bool is2005OrNewer = parser.Is2005OrNewer; - int count = 0; count = parameters.Count; @@ -6963,7 +6960,7 @@ internal string BuildParamList(TdsParser parser, SqlParameterCollection paramete { // func will change type to that with a 4 byte length if the type has a two // byte length and a parameter length > than that expressable in 2 bytes - mt = sqlParam.ValidateTypeLengths(is2005OrNewer); + mt = sqlParam.ValidateTypeLengths(); if ((!mt.IsPlp) && (sqlParam.Direction != ParameterDirection.Output)) { sqlParam.FixStreamDataForNonPLP(); diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs index e04302efdd..7fc4def9ea 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs @@ -1648,11 +1648,7 @@ internal SmiParameterMetaData GetMetadataForTypeInfo() internal SmiParameterMetaData MetaDataForSmi(out ParameterPeekAheadValue peekAhead) { peekAhead = null; - MetaType mt = ValidateTypeLengths( -#if NETFRAMEWORK - true /* 2005 or newer */ -#endif - ); + MetaType mt = ValidateTypeLengths(); long actualLen = GetActualSize(); long maxLen = Size; @@ -1989,11 +1985,7 @@ internal void Validate(int index, bool isCommandProc) // func will change type to that with a 4 byte length if the type has a two // byte length and a parameter length > than that expressible in 2 bytes - internal MetaType ValidateTypeLengths( -#if NETFRAMEWORK - bool is2005OrNewer -#endif - ) + internal MetaType ValidateTypeLengths() { MetaType mt = InternalMetaType; // Since the server will automatically reject any @@ -2025,11 +2017,7 @@ bool is2005OrNewer // Keeping these goals in mind - the following are the changes we are making long maxSizeInBytes; - if (mt.IsNCharType -#if NETFRAMEWORK - && is2005OrNewer -#endif - ) + if (mt.IsNCharType) { maxSizeInBytes = ((sizeInCharacters * sizeof(char)) > actualSizeInBytes) ? sizeInCharacters * sizeof(char) : actualSizeInBytes; } @@ -2046,60 +2034,8 @@ bool is2005OrNewer HasFlag(SqlParameterFlags.CoercedValueIsDataFeed) || (sizeInCharacters == -1) || (actualSizeInBytes == -1) - ) + ) { -#if NETFRAMEWORK - // is size > size able to be described by 2 bytes - if (is2005OrNewer) - { - // Convert the parameter to its max type - mt = MetaType.GetMaxMetaTypeFromMetaType(mt); - _metaType = mt; - InternalMetaType = mt; - if (!mt.IsPlp) - { - if (mt.SqlDbType == SqlDbType.Xml) - { - throw ADP.InvalidMetaDataValue(); //Xml should always have IsPartialLength = true - } - if ( - mt.SqlDbType == SqlDbType.NVarChar || - mt.SqlDbType == SqlDbType.VarChar || - mt.SqlDbType == SqlDbType.VarBinary - ) - { - Size = (int)SmiMetaData.UnlimitedMaxLengthIndicator; - } - } - } - else - { - switch (mt.SqlDbType) - { // widening the SqlDbType is automatic - case SqlDbType.Binary: - case SqlDbType.VarBinary: - mt = MetaType.GetMetaTypeFromSqlDbType(SqlDbType.Image, false); - _metaType = mt; // do not use SqlDbType property which calls PropertyTypeChanging resetting coerced value - InternalMetaType = mt; - break; - case SqlDbType.Char: - case SqlDbType.VarChar: - mt = MetaType.GetMetaTypeFromSqlDbType(SqlDbType.Text, false); - _metaType = mt; - InternalMetaType = mt; - break; - case SqlDbType.NChar: - case SqlDbType.NVarChar: - mt = MetaType.GetMetaTypeFromSqlDbType(SqlDbType.NText, false); - _metaType = mt; - InternalMetaType = mt; - break; - default: - Debug.Assert(false, "Missed metatype in SqlCommand.BuildParamList()"); - break; - } - } -#else mt = MetaType.GetMaxMetaTypeFromMetaType(mt); _metaType = mt; InternalMetaType = mt; @@ -2118,8 +2054,6 @@ bool is2005OrNewer Size = (int)SmiMetaData.UnlimitedMaxLengthIndicator; } } - -#endif } } return mt; From 784dc00e4593dc4351ed7004f83b6478931e37d5 Mon Sep 17 00:00:00 2001 From: David Engel Date: Fri, 27 May 2022 10:35:50 -0700 Subject: [PATCH 7/7] Sort usings --- .../src/Microsoft/Data/SqlClient/SqlParameter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs index 7fc4def9ea..c78ef7dfc7 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs @@ -13,11 +13,11 @@ using System.Globalization; using System.IO; using System.Reflection; +using System.Text; +using System.Threading; using System.Xml; using Microsoft.Data.Common; using Microsoft.Data.SqlClient.Server; -using System.Text; -using System.Threading; namespace Microsoft.Data.SqlClient {