diff --git a/release-notes/3.0/3.0.0.md b/release-notes/3.0/3.0.0.md index 6bef9eda1a..ef090c2f3c 100644 --- a/release-notes/3.0/3.0.0.md +++ b/release-notes/3.0/3.0.0.md @@ -102,9 +102,12 @@ public SqlCommand ``` API Usage examples can be found here: -[SqlConnection retry sample](..\..\doc\samples\SqlConfigurableRetryLogic_OpenConnection.cs) -[SqlCommand retry sample](..\..\doc\samples\SqlConfigurableRetryLogic_SqlCommand.cs) -[Sample for retry logic options](..\..\doc\samples\SqlConfigurableRetryLogic_SqlRetryLogicOptions.cs) + +[SqlConnection retry sample](../../doc/samples/SqlConfigurableRetryLogic_OpenConnection.cs) + +[SqlCommand retry sample](../../doc/samples/SqlConfigurableRetryLogic_SqlCommand.cs) + +[Sample for retry logic options](../../doc/samples/SqlConfigurableRetryLogic_SqlRetryLogicOptions.cs) New configuration sections have also been introduced to do the same registration from configuration files, without having to modify existing code: 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 69914d8812..8643b077f2 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj @@ -46,6 +46,9 @@ Microsoft\Data\Common\ActivityCorrelator.cs + + Microsoft\Data\Common\DbConnectionStringCommon.cs + Microsoft\Data\Common\DbConnectionPoolKey.cs @@ -154,6 +157,12 @@ Microsoft\Data\SqlClient\Server\SmiMetaData.cs + + Microsoft\Data\SqlClient\Server\SqlDataRecord.cs + + + Microsoft\Data\SqlClient\Server\SqlDataRecord.netcore.cs + Microsoft\Data\SqlClient\ColumnEncryptionKeyInfo.cs @@ -232,9 +241,15 @@ Microsoft\Data\SqlClient\SqlColumnEncryptionKeyStoreProvider.cs + + Microsoft\Data\SqlClient\SqlCommandBuilder.cs + Microsoft\Data\SqlClient\SqlCommandSet.cs + + Microsoft\Data\SqlClient\SqlConnectionPoolGroupProviderInfo.cs + Microsoft\Data\SqlClient\SqlConnectionPoolProviderInfo.cs @@ -244,9 +259,24 @@ Microsoft\Data\SqlClient\SqlDataAdapter.cs + + Microsoft\Data\SqlClient\SqlDependency.cs + + + Microsoft\Data\SqlClient\SqlEnums.cs + + + Microsoft\Data\SqlClient\SqlErrorCollection.cs + + + Microsoft\Data\SqlClient\SqlException.cs + Microsoft\Data\SqlClient\SqlInfoMessageEventHandler.cs + + Microsoft\Data\SqlClient\SqlNotificationEventArgs.cs + Microsoft\Data\SqlClient\SqlNotificationInfo.cs @@ -265,6 +295,9 @@ Microsoft\Data\SqlClient\SqlQueryMetadataCache.cs + + Microsoft\Data\SqlClient\SqlReferenceCollection.cs + Microsoft\Data\SqlClient\SqlRowUpdatedEvent.cs @@ -304,6 +337,9 @@ Microsoft\Data\SqlClient\Server\SqlRecordBuffer.cs + + Microsoft\Data\SqlClient\Server\ValueUtilsSmi.cs + Microsoft\Data\SqlClient\SignatureVerificationCache.cs @@ -322,6 +358,12 @@ Microsoft\Data\SqlClient\Server\SmiTypedGetterSetter.cs + + Microsoft\Data\SqlClient\Server\SmiEventSink.cs + + + Microsoft\Data\SqlClient\Server\SmiEventSink_Default.Common.cs + Microsoft\Data\SqlClient\Reliability\SqlRetryingEventArgs.cs @@ -458,15 +500,10 @@ - - - - - Common\Microsoft\Data\ProviderBase\DbConnectionInternal.cs @@ -503,11 +540,9 @@ - - @@ -515,26 +550,20 @@ Microsoft\Data\SqlClient\SqlConnectionTimeoutErrorInternal.cs - - - Microsoft\Data\SqlClient\SqlEnclaveSession.cs - - - diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SmiEventSink.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SmiEventSink.cs deleted file mode 100644 index 04ae3bedc5..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SmiEventSink.cs +++ /dev/null @@ -1,25 +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. - -namespace Microsoft.Data.SqlClient.Server -{ - // SqlEventSink is implemented by calling code. In all methods that accept - // a SqlEventSink directly the sink must be able to handle multiple callbacks - // without control returning from the original call. - - // Methods that do not accept SmiEventSync are (generally) ProcessEvent on - // the SmiEventStream methods returning a SmiEventStream and methods that - // are certain to never call to the server (most will, for in-proc back end). - - // Methods are commented with their corresponding TDS token - - // NOTE: Throwing from these methods will not usually produce the desired - // effect -- the managed to native boundary will eat any exceptions, - // and will cause a simple "Something bad happened" exception to be - // thrown in the native to managed boundary... - internal abstract class SmiEventSink - { - } -} - diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SqlDataRecord.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SqlDataRecord.cs deleted file mode 100644 index 9c588b810b..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SqlDataRecord.cs +++ /dev/null @@ -1,461 +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.Data; -using System.Data.SqlTypes; -using System.Diagnostics; -using Microsoft.Data.Common; -using Microsoft.Data.ProviderBase; - -namespace Microsoft.Data.SqlClient.Server -{ - /// - public class SqlDataRecord : IDataRecord - { - private readonly SmiRecordBuffer _recordBuffer; - private readonly SmiExtendedMetaData[] _columnSmiMetaData; - private readonly SmiEventSink_Default _eventSink; - private readonly SqlMetaData[] _columnMetaData; - private FieldNameLookup _fieldNameLookup; - private readonly bool _usesStringStorageForXml; - - private static readonly SmiMetaData s_maxNVarCharForXml = new SmiMetaData( - SqlDbType.NVarChar, - SmiMetaData.UnlimitedMaxLengthIndicator, - SmiMetaData.DefaultNVarChar_NoCollation.Precision, - SmiMetaData.DefaultNVarChar_NoCollation.Scale, - SmiMetaData.DefaultNVarChar.LocaleId, - SmiMetaData.DefaultNVarChar.CompareOptions, - userDefinedType: null - ); - - /// - public virtual int FieldCount => _columnMetaData.Length; - - /// - public virtual string GetName(int ordinal) => GetSqlMetaData(ordinal).Name; - - /// - public virtual string GetDataTypeName(int ordinal) - { - SqlMetaData metaData = GetSqlMetaData(ordinal); - if (metaData.SqlDbType == SqlDbType.Udt) - { - return metaData.UdtTypeName; - } - else - { - return MetaType.GetMetaTypeFromSqlDbType(metaData.SqlDbType, false).TypeName; - } - } - - /// - public virtual Type GetFieldType(int ordinal) => MetaType.GetMetaTypeFromSqlDbType(GetSqlMetaData(ordinal).SqlDbType, false).ClassType; - - /// - public virtual object GetValue(int ordinal) => ValueUtilsSmi.GetValue200(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual int GetValues(object[] values) - { - if (values == null) - { - throw ADP.ArgumentNull(nameof(values)); - } - - int copyLength = (values.Length < FieldCount) ? values.Length : FieldCount; - for (int i = 0; i < copyLength; i++) - { - values[i] = GetValue(i); - } - - return copyLength; - } - - /// - public virtual int GetOrdinal(string name) - { - if (_fieldNameLookup == null) - { - string[] names = new string[FieldCount]; - for (int i = 0; i < names.Length; i++) - { - names[i] = GetSqlMetaData(i).Name; - } - - _fieldNameLookup = new FieldNameLookup(names, -1); - } - - return _fieldNameLookup.GetOrdinal(name); - } - - /// - public virtual object this[int ordinal] => GetValue(ordinal); - - /// - public virtual object this[string name] => GetValue(GetOrdinal(name)); - - /// - public virtual bool GetBoolean(int ordinal) => ValueUtilsSmi.GetBoolean(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual byte GetByte(int ordinal) => ValueUtilsSmi.GetByte(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual long GetBytes(int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length) => ValueUtilsSmi.GetBytes(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), fieldOffset, buffer, bufferOffset, length, throwOnNull: true); - - /// - public virtual char GetChar(int ordinal) => throw ADP.NotSupported(); - - /// - public virtual long GetChars(int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length) => ValueUtilsSmi.GetChars(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), fieldOffset, buffer, bufferOffset, length); - - /// - public virtual Guid GetGuid(int ordinal) => ValueUtilsSmi.GetGuid(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual short GetInt16(int ordinal) => ValueUtilsSmi.GetInt16(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual int GetInt32(int ordinal) => ValueUtilsSmi.GetInt32(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual long GetInt64(int ordinal) => ValueUtilsSmi.GetInt64(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual float GetFloat(int ordinal) => ValueUtilsSmi.GetSingle(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual double GetDouble(int ordinal) => ValueUtilsSmi.GetDouble(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual string GetString(int ordinal) - { - SmiMetaData colMeta = GetSmiMetaData(ordinal); - if (_usesStringStorageForXml && colMeta.SqlDbType == SqlDbType.Xml) - { - return ValueUtilsSmi.GetString(_eventSink, _recordBuffer, ordinal, s_maxNVarCharForXml); - } - else - { - return ValueUtilsSmi.GetString(_eventSink, _recordBuffer, ordinal, colMeta); - } - } - - /// - public virtual decimal GetDecimal(int ordinal) => ValueUtilsSmi.GetDecimal(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual DateTime GetDateTime(int ordinal) => ValueUtilsSmi.GetDateTime(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual DateTimeOffset GetDateTimeOffset(int ordinal) => ValueUtilsSmi.GetDateTimeOffset(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual TimeSpan GetTimeSpan(int ordinal) => ValueUtilsSmi.GetTimeSpan(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual bool IsDBNull(int ordinal) - { - ThrowIfInvalidOrdinal(ordinal); - return ValueUtilsSmi.IsDBNull(_eventSink, _recordBuffer, ordinal); - } - - /// - // ISqlRecord implementation - public virtual SqlMetaData GetSqlMetaData(int ordinal) - { - ThrowIfInvalidOrdinal(ordinal); - return _columnMetaData[ordinal]; - } - - /// - public virtual Type GetSqlFieldType(int ordinal) => MetaType.GetMetaTypeFromSqlDbType(GetSqlMetaData(ordinal).SqlDbType, false).SqlType; - - /// - public virtual object GetSqlValue(int ordinal) => ValueUtilsSmi.GetSqlValue200(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual int GetSqlValues(object[] values) - { - if (null == values) - { - throw ADP.ArgumentNull(nameof(values)); - } - - int copyLength = (values.Length < FieldCount) ? values.Length : FieldCount; - for (int i = 0; i < copyLength; i++) - { - values[i] = GetSqlValue(i); - } - - return copyLength; - } - - /// - public virtual SqlBinary GetSqlBinary(int ordinal) => ValueUtilsSmi.GetSqlBinary(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlBytes GetSqlBytes(int ordinal) => ValueUtilsSmi.GetSqlBytes(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlXml GetSqlXml(int ordinal) => ValueUtilsSmi.GetSqlXml(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlBoolean GetSqlBoolean(int ordinal) => ValueUtilsSmi.GetSqlBoolean(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlByte GetSqlByte(int ordinal) => ValueUtilsSmi.GetSqlByte(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlChars GetSqlChars(int ordinal) => ValueUtilsSmi.GetSqlChars(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlInt16 GetSqlInt16(int ordinal) => ValueUtilsSmi.GetSqlInt16(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlInt32 GetSqlInt32(int ordinal) => ValueUtilsSmi.GetSqlInt32(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlInt64 GetSqlInt64(int ordinal) => ValueUtilsSmi.GetSqlInt64(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlSingle GetSqlSingle(int ordinal) => ValueUtilsSmi.GetSqlSingle(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlDouble GetSqlDouble(int ordinal) => ValueUtilsSmi.GetSqlDouble(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlMoney GetSqlMoney(int ordinal) => ValueUtilsSmi.GetSqlMoney(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlDateTime GetSqlDateTime(int ordinal) => ValueUtilsSmi.GetSqlDateTime(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlDecimal GetSqlDecimal(int ordinal) => ValueUtilsSmi.GetSqlDecimal(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlString GetSqlString(int ordinal) => ValueUtilsSmi.GetSqlString(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlGuid GetSqlGuid(int ordinal) => ValueUtilsSmi.GetSqlGuid(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - // ISqlUpdateableRecord Implementation - public virtual int SetValues(params object[] values) - { - if (values == null) - { - throw ADP.ArgumentNull(nameof(values)); - } - - // Allow values array longer than FieldCount, just ignore the extra cells. - int copyLength = (values.Length > FieldCount) ? FieldCount : values.Length; - - ExtendedClrTypeCode[] typeCodes = new ExtendedClrTypeCode[copyLength]; - - // Verify all data values as acceptable before changing current state. - for (int i = 0; i < copyLength; i++) - { - SqlMetaData metaData = GetSqlMetaData(i); - typeCodes[i] = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType( - metaData.SqlDbType, - isMultiValued: false, - values[i], - metaData.Type - ); - if (typeCodes[i] == ExtendedClrTypeCode.Invalid) - { - throw ADP.InvalidCast(); - } - } - - // Now move the data (it'll only throw if someone plays with the values array between - // the validation loop and here, or if an invalid UDT was sent). - for (int i = 0; i < copyLength; i++) - { - ValueUtilsSmi.SetCompatibleValueV200(_eventSink, _recordBuffer, i, GetSmiMetaData(i), values[i], typeCodes[i], offset: 0, length: 0, peekAhead: null); - } - - return copyLength; - } - - /// - public virtual void SetValue(int ordinal, object value) - { - SqlMetaData metaData = GetSqlMetaData(ordinal); - ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType( - metaData.SqlDbType, - isMultiValued: false, - value, - metaData.Type - ); - if (typeCode == ExtendedClrTypeCode.Invalid) - { - throw ADP.InvalidCast(); - } - - ValueUtilsSmi.SetCompatibleValueV200(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value, typeCode, offset: 0, length: 0, peekAhead: null); - } - - /// - public virtual void SetBoolean(int ordinal, bool value) => ValueUtilsSmi.SetBoolean(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetByte(int ordinal, byte value) => ValueUtilsSmi.SetByte(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetBytes(int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length) => ValueUtilsSmi.SetBytes(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), fieldOffset, buffer, bufferOffset, length); - - /// - public virtual void SetChar(int ordinal, char value) => throw ADP.NotSupported(); - - /// - public virtual void SetChars(int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length) => ValueUtilsSmi.SetChars(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), fieldOffset, buffer, bufferOffset, length); - - /// - public virtual void SetInt16(int ordinal, short value) => ValueUtilsSmi.SetInt16(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetInt32(int ordinal, int value) => ValueUtilsSmi.SetInt32(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetInt64(int ordinal, long value) => ValueUtilsSmi.SetInt64(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetFloat(int ordinal, float value) => ValueUtilsSmi.SetSingle(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - /// - public virtual void SetDouble(int ordinal, double value) => ValueUtilsSmi.SetDouble(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetString(int ordinal, string value) => ValueUtilsSmi.SetString(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetDecimal(int ordinal, decimal value) => ValueUtilsSmi.SetDecimal(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetDateTime(int ordinal, DateTime value) => ValueUtilsSmi.SetDateTime(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetTimeSpan(int ordinal, TimeSpan value) => ValueUtilsSmi.SetTimeSpan(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetDateTimeOffset(int ordinal, DateTimeOffset value) => ValueUtilsSmi.SetDateTimeOffset(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetDBNull(int ordinal) - { - ThrowIfInvalidOrdinal(ordinal); - ValueUtilsSmi.SetDBNull(_eventSink, _recordBuffer, ordinal, true); - } - - /// - public virtual void SetGuid(int ordinal, Guid value) => ValueUtilsSmi.SetGuid(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlBoolean(int ordinal, SqlBoolean value) => ValueUtilsSmi.SetSqlBoolean(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlByte(int ordinal, SqlByte value) => ValueUtilsSmi.SetSqlByte(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlInt16(int ordinal, SqlInt16 value) => ValueUtilsSmi.SetSqlInt16(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlInt32(int ordinal, SqlInt32 value) => ValueUtilsSmi.SetSqlInt32(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlInt64(int ordinal, SqlInt64 value) => ValueUtilsSmi.SetSqlInt64(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlSingle(int ordinal, SqlSingle value) => ValueUtilsSmi.SetSqlSingle(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlDouble(int ordinal, SqlDouble value) => ValueUtilsSmi.SetSqlDouble(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlMoney(int ordinal, SqlMoney value) => ValueUtilsSmi.SetSqlMoney(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlDateTime(int ordinal, SqlDateTime value) => ValueUtilsSmi.SetSqlDateTime(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlXml(int ordinal, SqlXml value) => ValueUtilsSmi.SetSqlXml(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlDecimal(int ordinal, SqlDecimal value) => ValueUtilsSmi.SetSqlDecimal(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlString(int ordinal, SqlString value) => ValueUtilsSmi.SetSqlString(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlBinary(int ordinal, SqlBinary value) => ValueUtilsSmi.SetSqlBinary(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlGuid(int ordinal, SqlGuid value) => ValueUtilsSmi.SetSqlGuid(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlChars(int ordinal, SqlChars value) => ValueUtilsSmi.SetSqlChars(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlBytes(int ordinal, SqlBytes value) => ValueUtilsSmi.SetSqlBytes(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - // SqlDataRecord public API - /// - public SqlDataRecord(params SqlMetaData[] metaData) - { - // Initial consistency check - if (metaData == null) - { - throw ADP.ArgumentNull(nameof(metaData)); - } - - _columnMetaData = new SqlMetaData[metaData.Length]; - _columnSmiMetaData = new SmiExtendedMetaData[metaData.Length]; - for (int i = 0; i < _columnSmiMetaData.Length; i++) - { - if (metaData[i] == null) - { - throw ADP.ArgumentNull($"{nameof(metaData)}[{i}]"); - } - _columnMetaData[i] = metaData[i]; - _columnSmiMetaData[i] = MetaDataUtilsSmi.SqlMetaDataToSmiExtendedMetaData(_columnMetaData[i]); - } - - _eventSink = new SmiEventSink_Default(); - _recordBuffer = new MemoryRecordBuffer(_columnSmiMetaData); - _usesStringStorageForXml = true; - _eventSink.ProcessMessagesAndThrow(); - } - - // - // SqlDataRecord private members - // - internal SmiRecordBuffer RecordBuffer => _recordBuffer; - - internal SqlMetaData[] InternalGetMetaData() => _columnMetaData; - - internal SmiExtendedMetaData[] InternalGetSmiMetaData() => _columnSmiMetaData; - - internal SmiExtendedMetaData GetSmiMetaData(int ordinal) - { - ThrowIfInvalidOrdinal(ordinal); - return _columnSmiMetaData[ordinal]; - } - - internal void ThrowIfInvalidOrdinal(int ordinal) - { - if (0 > ordinal || FieldCount <= ordinal) - { - throw ADP.IndexOutOfRange(ordinal); - } - } - - /// - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - IDataReader System.Data.IDataRecord.GetData(int ordinal) => throw ADP.NotSupported(); - } -} - diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionPoolGroupProviderInfo.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionPoolGroupProviderInfo.cs deleted file mode 100644 index 5a88dee38b..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlConnectionPoolGroupProviderInfo.cs +++ /dev/null @@ -1,91 +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 Microsoft.Data.ProviderBase; - -namespace Microsoft.Data.SqlClient -{ - sealed internal class SqlConnectionPoolGroupProviderInfo : DbConnectionPoolGroupProviderInfo - { - private string _alias; - private string _failoverPartner; - private bool _useFailoverPartner; - - internal SqlConnectionPoolGroupProviderInfo(SqlConnectionString connectionOptions) - { - // This is for the case where the user specified the failover partner - // in the connection string and we have not yet connected to get the - // env change. - _failoverPartner = connectionOptions.FailoverPartner; - - if (string.IsNullOrEmpty(_failoverPartner)) - { - _failoverPartner = null; - } - } - - internal string FailoverPartner - { - get - { - return _failoverPartner; - } - } - - internal bool UseFailoverPartner - { - get - { - return _useFailoverPartner; - } - } - - internal void AliasCheck(string server) - { - if (_alias != server) - { - lock (this) - { - if (null == _alias) - { - _alias = server; - } - else if (_alias != server) - { - SqlClientEventSource.Log.TryTraceEvent("SqlConnectionPoolGroupProviderInfo.AliasCheck | Info | Alias change detected. Clearing PoolGroup."); - base.PoolGroup.Clear(); - _alias = server; - } - } - } - } - - - internal void FailoverCheck(SqlInternalConnection connection, bool actualUseFailoverPartner, SqlConnectionString userConnectionOptions, string actualFailoverPartner) - { - if (UseFailoverPartner != actualUseFailoverPartner) - { - SqlClientEventSource.Log.TryTraceEvent("SqlConnectionPoolGroupProviderInfo.FailoverCheck | Info | Failover detected. Failover partner '{0}'. Clearing PoolGroup", actualFailoverPartner); - base.PoolGroup.Clear(); - _useFailoverPartner = actualUseFailoverPartner; - } - // Only construct a new permission set when we're connecting to the - // primary data source, not the failover partner. - if (!_useFailoverPartner && _failoverPartner != actualFailoverPartner) - { - // NOTE: we optimistically generate the permission set to keep - // lock short, but we only do this when we get a new - // failover partner. - - lock (this) - { - if (_failoverPartner != actualFailoverPartner) - { - _failoverPartner = actualFailoverPartner; - } - } - } - } - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlErrorCollection.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlErrorCollection.cs deleted file mode 100644 index 80d625a38b..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlErrorCollection.cs +++ /dev/null @@ -1,46 +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; -using System.Collections.Generic; - -namespace Microsoft.Data.SqlClient -{ - /// - public sealed class SqlErrorCollection : ICollection - { - // Ideally this would be typed as List, but that would make the non-generic - // CopyTo behave differently than the full framework (which uses ArrayList), throwing - // ArgumentException instead of the expected InvalidCastException for incompatible types. - // Instead, we use List, which makes the non-generic CopyTo behave like - // ArrayList.CopyTo. - private readonly List _errors = new List(); - - internal SqlErrorCollection() { } - - /// - public void CopyTo(Array array, int index) => ((ICollection)_errors).CopyTo(array, index); - - /// - public void CopyTo(SqlError[] array, int index) => _errors.CopyTo(array, index); - - /// - public int Count => _errors.Count; - - /// - object ICollection.SyncRoot => this; - - /// - bool ICollection.IsSynchronized => false; - - /// - public SqlError this[int index] => (SqlError)_errors[index]; - - /// - public IEnumerator GetEnumerator() => _errors.GetEnumerator(); - - internal void Add(SqlError error) => _errors.Add(error); - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs index 9b85ced97f..484e2233a9 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs @@ -1635,7 +1635,7 @@ private void LoginNoFailover(ServerInfo serverInfo, // We must wait for CompleteLogin to finish for to have the // env change from the server to know its designated failover // partner; save this information in _currentFailoverPartner. - PoolGroupProviderInfo.FailoverCheck(this, false, connectionOptions, ServerProvidedFailOverPartner); + PoolGroupProviderInfo.FailoverCheck(false, connectionOptions, ServerProvidedFailOverPartner); } CurrentDataSource = originalServerInfo.UserServerName; } @@ -1841,7 +1841,7 @@ TimeoutTimer timeout // We must wait for CompleteLogin to finish for to have the // env change from the server to know its designated failover // partner; save this information in _currentFailoverPartner. - PoolGroupProviderInfo.FailoverCheck(this, useFailoverHost, connectionOptions, ServerProvidedFailOverPartner); + PoolGroupProviderInfo.FailoverCheck(useFailoverHost, connectionOptions, ServerProvidedFailOverPartner); } CurrentDataSource = (useFailoverHost ? failoverHost : primaryServerInfo.UserServerName); } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlNotificationEventArgs.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlNotificationEventArgs.cs deleted file mode 100644 index 0e37f820ea..0000000000 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlNotificationEventArgs.cs +++ /dev/null @@ -1,35 +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; - -namespace Microsoft.Data.SqlClient -{ - /// - public class SqlNotificationEventArgs : EventArgs - { - private SqlNotificationType _type; - private SqlNotificationInfo _info; - private SqlNotificationSource _source; - - /// - public SqlNotificationEventArgs(SqlNotificationType type, SqlNotificationInfo info, SqlNotificationSource source) - { - _info = info; - _source = source; - _type = type; - } - - /// - public SqlNotificationType Type => _type; - - /// - public SqlNotificationInfo Info => _info; - - /// - public SqlNotificationSource Source => _source; - - internal static SqlNotificationEventArgs s_notifyError = new SqlNotificationEventArgs(SqlNotificationType.Subscribe, SqlNotificationInfo.Error, SqlNotificationSource.Object); - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Resources/StringsHelper.cs b/src/Microsoft.Data.SqlClient/netcore/src/Resources/StringsHelper.cs index a2ee7e51d2..4b61d284ff 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Resources/StringsHelper.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Resources/StringsHelper.cs @@ -158,6 +158,7 @@ internal class ResourceNames internal const string TCE_DbConnectionString_AttestationProtocol = @"Specifies an attestation protocol for its corresponding enclave attestation service."; internal const string TCE_DbConnectionString_IPAddressPreference = @"Specifies an IP address preference when connecting to SQL instances."; internal const string SqlConnection_ServerProcessId = @"Server Process Id (SPID) of the active connection."; + internal const string SqlCommandBuilder_DataAdapter = @"The DataAdapter for which to automatically generate SqlCommands."; } } } 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 8f15f1b7a5..a5a4109baa 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj @@ -101,6 +101,9 @@ Microsoft\Data\Common\ActivityCorrelator.cs + + Microsoft\Data\Common\DbConnectionStringCommon.cs + Microsoft\Data\Common\DbConnectionPoolKey.cs @@ -222,12 +225,33 @@ Microsoft\Data\SqlClient\Server\SqlRecordBuffer.cs + + Microsoft\Data\SqlClient\Server\SqlDataRecord.cs + + + Microsoft\Data\SqlClient\Server\SqlDataRecord.netfx.cs + Microsoft\Data\SqlClient\Server\SmiMetaData.cs + + Microsoft\Data\SqlClient\Server\ValueUtilsSmi.cs + + + Microsoft\Data\SqlClient\Server\ValueUtilsSmi.netfx.cs + Microsoft\Data\SqlClient\ColumnEncryptionKeyInfo.cs + + Microsoft\Data\SqlClient\Server\SmiEventSink.cs + + + Microsoft\Data\SqlClient\Server\SmiEventSink_Default.Common.cs + + + Microsoft\Data\SqlClient\Server\SmiEventSink_Default.netfx.cs + Microsoft\Data\SqlClient\OnChangedEventHandler.cs @@ -303,24 +327,45 @@ Microsoft\Data\SqlClient\SqlColumnEncryptionKeyStoreProvider.cs + + Microsoft\Data\SqlClient\SqlCommandBuilder.cs + Microsoft\Data\SqlClient\SqlCommandSet.cs + + Microsoft\Data\SqlClient\SqlConnectionPoolGroupProviderInfo.cs + Microsoft\Data\SqlClient\SqlConnectionPoolProviderInfo.cs Microsoft\Data\SqlClient\SqlDataAdapter.cs + + Microsoft\Data\SqlClient\SqlDependency.cs + Microsoft\Data\SqlClient\SqlEnclaveAttestationParameters.Crypto.cs Microsoft\Data\SqlClient\SqlEnclaveSession.cs + + Microsoft\Data\SqlClient\SqlEnums.cs + + + Microsoft\Data\SqlClient\SqlErrorCollection.cs + + + Microsoft\Data\SqlClient\SqlException.cs + Microsoft\Data\SqlClient\SqlInfoMessageEventHandler.cs + + Microsoft\Data\SqlClient\SqlNotificationEventArgs.cs + Microsoft\Data\SqlClient\SqlNotificationInfo.cs @@ -336,6 +381,9 @@ Microsoft\Data\SqlClient\SqlQueryMetadataCache.cs + + Microsoft\Data\SqlClient\SqlReferenceCollection.cs + Microsoft\Data\SqlClient\SqlRowUpdatedEvent.cs @@ -463,7 +511,6 @@ - @@ -481,11 +528,9 @@ - - @@ -498,22 +543,16 @@ - - - - - - @@ -542,7 +581,6 @@ - @@ -560,8 +598,6 @@ - - @@ -570,7 +606,6 @@ - diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Common/DbConnectionStringCommon.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Common/DbConnectionStringCommon.cs deleted file mode 100644 index 0e1a941d06..0000000000 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/Common/DbConnectionStringCommon.cs +++ /dev/null @@ -1,1387 +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.Diagnostics; -using System.Globalization; -using Microsoft.Data.SqlClient; - -namespace Microsoft.Data.Common -{ - - /* - internal sealed class NamedConnectionStringConverter : StringConverter { - - public NamedConnectionStringConverter() { - } - - public override bool GetStandardValuesSupported(ITypeDescriptorContext context) { - return true; - } - - public override bool GetStandardValuesExclusive(ITypeDescriptorContext context) { - // Although theoretically this could be true, some people may want to just type in a name - return false; - } - - public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) { - StandardValuesCollection standardValues = null; - if (null != context) { - DbConnectionStringBuilder instance = (context.Instance as DbConnectionStringBuilder); - if (null != instance) { - string myProviderName = instance.GetType().Namespace; - - List myConnectionNames = new List(); - foreach(System.Configuration.ConnectionStringSetting setting in System.Configuration.ConfigurationManager.ConnectionStrings) { - if (myProviderName.EndsWith(setting.ProviderName)) { - myConnectionNames.Add(setting.ConnectionName); - } - } - standardValues = new StandardValuesCollection(myConnectionNames); - } - } - return standardValues; - } - } - */ - - - [Serializable()] - internal sealed class ReadOnlyCollection : System.Collections.ICollection, ICollection - { - private T[] _items; - - internal ReadOnlyCollection(T[] items) - { - _items = items; -#if DEBUG - for (int i = 0; i < items.Length; ++i) - { - Debug.Assert(null != items[i], "null item"); - } -#endif - } - - public void CopyTo(T[] array, int arrayIndex) - { - Array.Copy(_items, 0, array, arrayIndex, _items.Length); - } - - void System.Collections.ICollection.CopyTo(Array array, int arrayIndex) - { - Array.Copy(_items, 0, array, arrayIndex, _items.Length); - } - - - IEnumerator IEnumerable.GetEnumerator() - { - return new Enumerator(_items); - } - - public System.Collections.IEnumerator GetEnumerator() - { - return new Enumerator(_items); - } - - bool System.Collections.ICollection.IsSynchronized - { - get { return false; } - } - - Object System.Collections.ICollection.SyncRoot - { - get { return _items; } - } - - bool ICollection.IsReadOnly - { - get { return true; } - } - - void ICollection.Add(T value) - { - throw new NotSupportedException(); - } - - void ICollection.Clear() - { - throw new NotSupportedException(); - } - - bool ICollection.Contains(T value) - { - return Array.IndexOf(_items, value) >= 0; - } - - bool ICollection.Remove(T value) - { - throw new NotSupportedException(); - } - - public int Count - { - get { return _items.Length; } - } - - [Serializable()] - internal struct Enumerator : IEnumerator, System.Collections.IEnumerator - { // based on List.Enumerator - private K[] _items; - private int _index; - - internal Enumerator(K[] items) - { - _items = items; - _index = -1; - } - - public void Dispose() - { - } - - public bool MoveNext() - { - return (++_index < _items.Length); - } - - public K Current - { - get - { - return _items[_index]; - } - } - - Object System.Collections.IEnumerator.Current - { - get - { - return _items[_index]; - } - } - - void System.Collections.IEnumerator.Reset() - { - _index = -1; - } - } - } - - internal static class DbConnectionStringBuilderUtil - { - - internal static bool ConvertToBoolean(object value) - { - Debug.Assert(null != value, "ConvertToBoolean(null)"); - string svalue = (value as string); - if (null != svalue) - { - if (StringComparer.OrdinalIgnoreCase.Equals(svalue, "true") || StringComparer.OrdinalIgnoreCase.Equals(svalue, "yes")) - return true; - else if (StringComparer.OrdinalIgnoreCase.Equals(svalue, "false") || StringComparer.OrdinalIgnoreCase.Equals(svalue, "no")) - return false; - else - { - string tmp = svalue.Trim(); // Remove leading & trailing white space. - if (StringComparer.OrdinalIgnoreCase.Equals(tmp, "true") || StringComparer.OrdinalIgnoreCase.Equals(tmp, "yes")) - return true; - else if (StringComparer.OrdinalIgnoreCase.Equals(tmp, "false") || StringComparer.OrdinalIgnoreCase.Equals(tmp, "no")) - return false; - } - return Boolean.Parse(svalue); - } - try - { - return ((IConvertible)value).ToBoolean(CultureInfo.InvariantCulture); - } - catch (InvalidCastException e) - { - throw ADP.ConvertFailed(value.GetType(), typeof(Boolean), e); - } - } - - internal static bool ConvertToIntegratedSecurity(object value) - { - Debug.Assert(null != value, "ConvertToIntegratedSecurity(null)"); - string svalue = (value as string); - if (null != svalue) - { - if (StringComparer.OrdinalIgnoreCase.Equals(svalue, "sspi") || StringComparer.OrdinalIgnoreCase.Equals(svalue, "true") || StringComparer.OrdinalIgnoreCase.Equals(svalue, "yes")) - return true; - else if (StringComparer.OrdinalIgnoreCase.Equals(svalue, "false") || StringComparer.OrdinalIgnoreCase.Equals(svalue, "no")) - return false; - else - { - string tmp = svalue.Trim(); // Remove leading & trailing white space. - if (StringComparer.OrdinalIgnoreCase.Equals(tmp, "sspi") || StringComparer.OrdinalIgnoreCase.Equals(tmp, "true") || StringComparer.OrdinalIgnoreCase.Equals(tmp, "yes")) - return true; - else if (StringComparer.OrdinalIgnoreCase.Equals(tmp, "false") || StringComparer.OrdinalIgnoreCase.Equals(tmp, "no")) - return false; - } - return Boolean.Parse(svalue); - } - try - { - return ((IConvertible)value).ToBoolean(CultureInfo.InvariantCulture); - } - catch (InvalidCastException e) - { - throw ADP.ConvertFailed(value.GetType(), typeof(Boolean), e); - } - } - - internal static int ConvertToInt32(object value) - { - try - { - return ((IConvertible)value).ToInt32(CultureInfo.InvariantCulture); - } - catch (InvalidCastException e) - { - throw ADP.ConvertFailed(value.GetType(), typeof(Int32), e); - } - } - - internal static string ConvertToString(object value) - { - try - { - return ((IConvertible)value).ToString(CultureInfo.InvariantCulture); - } - catch (InvalidCastException e) - { - throw ADP.ConvertFailed(value.GetType(), typeof(String), e); - } - } - - #region <> - const string PoolBlockingPeriodAutoString = "Auto"; - const string PoolBlockingPeriodAlwaysBlockString = "AlwaysBlock"; - const string PoolBlockingPeriodNeverBlockString = "NeverBlock"; - - internal static bool TryConvertToPoolBlockingPeriod(string value, out PoolBlockingPeriod result) - { - Debug.Assert(Enum.GetNames(typeof(PoolBlockingPeriod)).Length == 3, "PoolBlockingPeriod enum has changed, update needed"); - Debug.Assert(null != value, "TryConvertToPoolBlockingPeriod(null,...)"); - - if (StringComparer.OrdinalIgnoreCase.Equals(value, PoolBlockingPeriodAutoString)) - { - result = PoolBlockingPeriod.Auto; - return true; - } - else if (StringComparer.OrdinalIgnoreCase.Equals(value, PoolBlockingPeriodAlwaysBlockString)) - { - result = PoolBlockingPeriod.AlwaysBlock; - return true; - } - else if (StringComparer.OrdinalIgnoreCase.Equals(value, PoolBlockingPeriodNeverBlockString)) - { - result = PoolBlockingPeriod.NeverBlock; - return true; - } - else - { - result = DbConnectionStringDefaults.PoolBlockingPeriod; - return false; - } - } - - internal static bool IsValidPoolBlockingPeriodValue(PoolBlockingPeriod value) - { - Debug.Assert(Enum.GetNames(typeof(PoolBlockingPeriod)).Length == 3, "PoolBlockingPeriod enum has changed, update needed"); - return value == PoolBlockingPeriod.Auto || value == PoolBlockingPeriod.AlwaysBlock || value == PoolBlockingPeriod.NeverBlock; - } - - internal static string PoolBlockingPeriodToString(PoolBlockingPeriod value) - { - Debug.Assert(IsValidPoolBlockingPeriodValue(value)); - - if (value == PoolBlockingPeriod.AlwaysBlock) - { - return PoolBlockingPeriodAlwaysBlockString; - } - if (value == PoolBlockingPeriod.NeverBlock) - { - return PoolBlockingPeriodNeverBlockString; - } - else - { - return PoolBlockingPeriodAutoString; - } - } - - /// - /// This method attempts to convert the given value to a PoolBlockingPeriod enum. The algorithm is: - /// * if the value is from type string, it will be matched against PoolBlockingPeriod enum names only, using ordinal, case-insensitive comparer - /// * if the value is from type PoolBlockingPeriod, it will be used as is - /// * if the value is from integral type (SByte, Int16, Int32, Int64, Byte, UInt16, UInt32, or UInt64), it will be converted to enum - /// * if the value is another enum or any other type, it will be blocked with an appropriate ArgumentException - /// - /// in any case above, if the converted value is out of valid range, the method raises ArgumentOutOfRangeException. - /// - /// PoolBlockingPeriod value in the valid range - internal static PoolBlockingPeriod ConvertToPoolBlockingPeriod(string keyword, object value) - { - Debug.Assert(null != value, "ConvertToPoolBlockingPeriod(null)"); - string sValue = (value as string); - PoolBlockingPeriod result; - if (null != sValue) - { - // We could use Enum.TryParse here, but it accepts value combinations like - // "ReadOnly, ReadWrite" which are unwelcome here - // Also, Enum.TryParse is 100x slower than plain StringComparer.OrdinalIgnoreCase.Equals method. - - if (TryConvertToPoolBlockingPeriod(sValue, out result)) - { - return result; - } - - // try again after remove leading & trailing whitespaces. - sValue = sValue.Trim(); - if (TryConvertToPoolBlockingPeriod(sValue, out result)) - { - return result; - } - - // string values must be valid - throw ADP.InvalidConnectionOptionValue(keyword); - } - else - { - // the value is not string, try other options - PoolBlockingPeriod eValue; - - if (value is PoolBlockingPeriod) - { - // quick path for the most common case - eValue = (PoolBlockingPeriod)value; - } - else if (value.GetType().IsEnum) - { - // explicitly block scenarios in which user tries to use wrong enum types, like: - // builder["PoolBlockingPeriod"] = EnvironmentVariableTarget.Process; - // workaround: explicitly cast non-PoolBlockingPeriod enums to int - throw ADP.ConvertFailed(value.GetType(), typeof(PoolBlockingPeriod), null); - } - else - { - try - { - // Enum.ToObject allows only integral and enum values (enums are blocked above), raising ArgumentException for the rest - eValue = (PoolBlockingPeriod)Enum.ToObject(typeof(PoolBlockingPeriod), value); - } - catch (ArgumentException e) - { - // to be consistent with the messages we send in case of wrong type usage, replace - // the error with our exception, and keep the original one as inner one for troubleshooting - throw ADP.ConvertFailed(value.GetType(), typeof(PoolBlockingPeriod), e); - } - } - - // ensure value is in valid range - if (IsValidPoolBlockingPeriodValue(eValue)) - { - return eValue; - } - else - { - throw ADP.InvalidEnumerationValue(typeof(ApplicationIntent), (int)eValue); - } - } - } - #endregion - - const string ApplicationIntentReadWriteString = "ReadWrite"; - const string ApplicationIntentReadOnlyString = "ReadOnly"; - - internal static bool TryConvertToApplicationIntent(string value, out ApplicationIntent result) - { - Debug.Assert(Enum.GetNames(typeof(ApplicationIntent)).Length == 2, "ApplicationIntent enum has changed, update needed"); - Debug.Assert(null != value, "TryConvertToApplicationIntent(null,...)"); - - if (StringComparer.OrdinalIgnoreCase.Equals(value, ApplicationIntentReadOnlyString)) - { - result = ApplicationIntent.ReadOnly; - return true; - } - else if (StringComparer.OrdinalIgnoreCase.Equals(value, ApplicationIntentReadWriteString)) - { - result = ApplicationIntent.ReadWrite; - return true; - } - else - { - result = DbConnectionStringDefaults.ApplicationIntent; - return false; - } - } - - internal static bool IsValidApplicationIntentValue(ApplicationIntent value) - { - Debug.Assert(Enum.GetNames(typeof(ApplicationIntent)).Length == 2, "ApplicationIntent enum has changed, update needed"); - return value == ApplicationIntent.ReadOnly || value == ApplicationIntent.ReadWrite; - } - - internal static string ApplicationIntentToString(ApplicationIntent value) - { - Debug.Assert(IsValidApplicationIntentValue(value)); - if (value == ApplicationIntent.ReadOnly) - { - return ApplicationIntentReadOnlyString; - } - else - { - return ApplicationIntentReadWriteString; - } - } - - /// - /// This method attempts to convert the given value tp ApplicationIntent enum. The algorithm is: - /// * if the value is from type string, it will be matched against ApplicationIntent enum names only, using ordinal, case-insensitive comparer - /// * if the value is from type ApplicationIntent, it will be used as is - /// * if the value is from integral type (SByte, Int16, Int32, Int64, Byte, UInt16, UInt32, or UInt64), it will be converted to enum - /// * if the value is another enum or any other type, it will be blocked with an appropriate ArgumentException - /// - /// in any case above, if the converted value is out of valid range, the method raises ArgumentOutOfRangeException. - /// - /// application intent value in the valid range - internal static ApplicationIntent ConvertToApplicationIntent(string keyword, object value) - { - Debug.Assert(null != value, "ConvertToApplicationIntent(null)"); - string sValue = (value as string); - ApplicationIntent result; - if (null != sValue) - { - // We could use Enum.TryParse here, but it accepts value combinations like - // "ReadOnly, ReadWrite" which are unwelcome here - // Also, Enum.TryParse is 100x slower than plain StringComparer.OrdinalIgnoreCase.Equals method. - - if (TryConvertToApplicationIntent(sValue, out result)) - { - return result; - } - - // try again after remove leading & trailing whitespaces. - sValue = sValue.Trim(); - if (TryConvertToApplicationIntent(sValue, out result)) - { - return result; - } - - // string values must be valid - throw ADP.InvalidConnectionOptionValue(keyword); - } - else - { - // the value is not string, try other options - ApplicationIntent eValue; - - if (value is ApplicationIntent) - { - // quick path for the most common case - eValue = (ApplicationIntent)value; - } - else if (value.GetType().IsEnum) - { - // explicitly block scenarios in which user tries to use wrong enum types, like: - // builder["ApplicationIntent"] = EnvironmentVariableTarget.Process; - // workaround: explicitly cast non-ApplicationIntent enums to int - throw ADP.ConvertFailed(value.GetType(), typeof(ApplicationIntent), null); - } - else - { - try - { - // Enum.ToObject allows only integral and enum values (enums are blocked above), raising ArgumentException for the rest - eValue = (ApplicationIntent)Enum.ToObject(typeof(ApplicationIntent), value); - } - catch (ArgumentException e) - { - // to be consistent with the messages we send in case of wrong type usage, replace - // the error with our exception, and keep the original one as inner one for troubleshooting - throw ADP.ConvertFailed(value.GetType(), typeof(ApplicationIntent), e); - } - } - - // ensure value is in valid range - if (IsValidApplicationIntentValue(eValue)) - { - return eValue; - } - else - { - throw ADP.InvalidEnumerationValue(typeof(ApplicationIntent), (int)eValue); - } - } - } - - const string SqlPasswordString = "Sql Password"; - const string ActiveDirectoryPasswordString = "Active Directory Password"; - const string ActiveDirectoryIntegratedString = "Active Directory Integrated"; - const string ActiveDirectoryInteractiveString = "Active Directory Interactive"; - const string ActiveDirectoryServicePrincipalString = "Active Directory Service Principal"; - const string ActiveDirectoryDeviceCodeFlowString = "Active Directory Device Code Flow"; - internal const string ActiveDirectoryManagedIdentityString = "Active Directory Managed Identity"; - internal const string ActiveDirectoryMSIString = "Active Directory MSI"; - internal const string ActiveDirectoryDefaultString = "Active Directory Default"; - // const string SqlCertificateString = "Sql Certificate"; - -#if DEBUG - private static string[] s_supportedAuthenticationModes = - { - "NotSpecified", - "SqlPassword", - "ActiveDirectoryPassword", - "ActiveDirectoryIntegrated", - "ActiveDirectoryInteractive", - "ActiveDirectoryServicePrincipal", - "ActiveDirectoryDeviceCodeFlow", - "ActiveDirectoryManagedIdentity", - "ActiveDirectoryMSI", - "ActiveDirectoryDefault" - }; - - private static bool IsValidAuthenticationMethodEnum() - { - string[] names = Enum.GetNames(typeof(SqlAuthenticationMethod)); - int l = s_supportedAuthenticationModes.Length; - bool listValid; - if (listValid = names.Length == l) - { - for (int i = 0; i < l; i++) - { - if (s_supportedAuthenticationModes[i].CompareTo(names[i]) != 0) - { - listValid = false; - } - } - } - return listValid; - } -#endif - - internal static bool TryConvertToAuthenticationType(string value, out SqlAuthenticationMethod result) - { -#if DEBUG - Debug.Assert(IsValidAuthenticationMethodEnum(), "SqlAuthenticationMethod enum has changed, update needed"); -#endif - bool isSuccess = false; - - if (StringComparer.InvariantCultureIgnoreCase.Equals(value, SqlPasswordString) - || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.SqlPassword, CultureInfo.InvariantCulture))) - { - result = SqlAuthenticationMethod.SqlPassword; - isSuccess = true; - } - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryPasswordString) - || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryPassword, CultureInfo.InvariantCulture))) - { - result = SqlAuthenticationMethod.ActiveDirectoryPassword; - isSuccess = true; - } - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryIntegratedString) - || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryIntegrated, CultureInfo.InvariantCulture))) - { - result = SqlAuthenticationMethod.ActiveDirectoryIntegrated; - isSuccess = true; - } - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryInteractiveString) - || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryInteractive, CultureInfo.InvariantCulture))) - { - result = SqlAuthenticationMethod.ActiveDirectoryInteractive; - isSuccess = true; - } - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryServicePrincipalString) - || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryServicePrincipal, CultureInfo.InvariantCulture))) - { - result = SqlAuthenticationMethod.ActiveDirectoryServicePrincipal; - isSuccess = true; - } - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryDeviceCodeFlowString) - || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow, CultureInfo.InvariantCulture))) - { - result = SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow; - isSuccess = true; - } - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryManagedIdentityString) - || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, CultureInfo.InvariantCulture))) - { - result = SqlAuthenticationMethod.ActiveDirectoryManagedIdentity; - isSuccess = true; - } - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryMSIString) - || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryMSI, CultureInfo.InvariantCulture))) - { - result = SqlAuthenticationMethod.ActiveDirectoryMSI; - isSuccess = true; - } - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryDefaultString) - || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryDefault, CultureInfo.InvariantCulture))) - { - result = SqlAuthenticationMethod.ActiveDirectoryDefault; - isSuccess = true; - } -#if ADONET_CERT_AUTH - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, SqlCertificateString) - || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.SqlCertificate, CultureInfo.InvariantCulture))) { - result = SqlAuthenticationMethod.SqlCertificate; - isSuccess = true; - } -#endif - else - { - result = DbConnectionStringDefaults.Authentication; - } - return isSuccess; - } - - /// - /// Column Encryption Setting. - /// - const string ColumnEncryptionSettingEnabledString = "Enabled"; - const string ColumnEncryptionSettingDisabledString = "Disabled"; - - /// - /// Convert a string value to the corresponding SqlConnectionColumnEncryptionSetting. - /// - /// - /// - /// - internal static bool TryConvertToColumnEncryptionSetting(string value, out SqlConnectionColumnEncryptionSetting result) - { - bool isSuccess = false; - - if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ColumnEncryptionSettingEnabledString)) - { - result = SqlConnectionColumnEncryptionSetting.Enabled; - isSuccess = true; - } - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ColumnEncryptionSettingDisabledString)) - { - result = SqlConnectionColumnEncryptionSetting.Disabled; - isSuccess = true; - } - else - { - result = DbConnectionStringDefaults.ColumnEncryptionSetting; - } - - return isSuccess; - } - - /// - /// Is it a valid connection level column encryption setting ? - /// - /// - /// - internal static bool IsValidColumnEncryptionSetting(SqlConnectionColumnEncryptionSetting value) - { - Debug.Assert(Enum.GetNames(typeof(SqlConnectionColumnEncryptionSetting)).Length == 2, "SqlConnectionColumnEncryptionSetting enum has changed, update needed"); - return value == SqlConnectionColumnEncryptionSetting.Enabled || value == SqlConnectionColumnEncryptionSetting.Disabled; - } - - /// - /// Convert connection level column encryption setting value to string. - /// - /// - /// - internal static string ColumnEncryptionSettingToString(SqlConnectionColumnEncryptionSetting value) - { - Debug.Assert(IsValidColumnEncryptionSetting(value), "value is not a valid connection level column encryption setting."); - - switch (value) - { - case SqlConnectionColumnEncryptionSetting.Enabled: - return ColumnEncryptionSettingEnabledString; - case SqlConnectionColumnEncryptionSetting.Disabled: - return ColumnEncryptionSettingDisabledString; - - default: - return null; - } - } - - internal static bool IsValidAuthenticationTypeValue(SqlAuthenticationMethod value) - { - Debug.Assert(Enum.GetNames(typeof(SqlAuthenticationMethod)).Length == 10, "SqlAuthenticationMethod enum has changed, update needed"); - return value == SqlAuthenticationMethod.SqlPassword - || value == SqlAuthenticationMethod.ActiveDirectoryPassword - || value == SqlAuthenticationMethod.ActiveDirectoryIntegrated - || value == SqlAuthenticationMethod.ActiveDirectoryInteractive - || value == SqlAuthenticationMethod.ActiveDirectoryServicePrincipal - || value == SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow - || value == SqlAuthenticationMethod.ActiveDirectoryManagedIdentity - || value == SqlAuthenticationMethod.ActiveDirectoryMSI - || value == SqlAuthenticationMethod.ActiveDirectoryDefault -#if ADONET_CERT_AUTH - || value == SqlAuthenticationMethod.SqlCertificate -#endif - || value == SqlAuthenticationMethod.NotSpecified; - } - - internal static string AuthenticationTypeToString(SqlAuthenticationMethod value) - { - Debug.Assert(IsValidAuthenticationTypeValue(value)); - - switch (value) - { - case SqlAuthenticationMethod.SqlPassword: - return SqlPasswordString; - case SqlAuthenticationMethod.ActiveDirectoryPassword: - return ActiveDirectoryPasswordString; - case SqlAuthenticationMethod.ActiveDirectoryIntegrated: - return ActiveDirectoryIntegratedString; - case SqlAuthenticationMethod.ActiveDirectoryInteractive: - return ActiveDirectoryInteractiveString; - case SqlAuthenticationMethod.ActiveDirectoryServicePrincipal: - return ActiveDirectoryServicePrincipalString; - case SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow: - return ActiveDirectoryDeviceCodeFlowString; - case SqlAuthenticationMethod.ActiveDirectoryManagedIdentity: - return ActiveDirectoryManagedIdentityString; - case SqlAuthenticationMethod.ActiveDirectoryMSI: - return ActiveDirectoryMSIString; - case SqlAuthenticationMethod.ActiveDirectoryDefault: - return ActiveDirectoryDefaultString; -#if ADONET_CERT_AUTH - case SqlAuthenticationMethod.SqlCertificate: - return SqlCertificateString; -#endif - default: - return null; - } - } - - internal static SqlAuthenticationMethod ConvertToAuthenticationType(string keyword, object value) - { - if (null == value) - { - return DbConnectionStringDefaults.Authentication; - } - - string sValue = (value as string); - SqlAuthenticationMethod result; - if (null != sValue) - { - if (TryConvertToAuthenticationType(sValue, out result)) - { - return result; - } - - // try again after remove leading & trailing whitespaces. - sValue = sValue.Trim(); - if (TryConvertToAuthenticationType(sValue, out result)) - { - return result; - } - - // string values must be valid - throw ADP.InvalidConnectionOptionValue(keyword); - } - else - { - // the value is not string, try other options - SqlAuthenticationMethod eValue; - - if (value is SqlAuthenticationMethod) - { - // quick path for the most common case - eValue = (SqlAuthenticationMethod)value; - } - else if (value.GetType().IsEnum) - { - // explicitly block scenarios in which user tries to use wrong enum types, like: - // builder["ApplicationIntent"] = EnvironmentVariableTarget.Process; - // workaround: explicitly cast non-ApplicationIntent enums to int - throw ADP.ConvertFailed(value.GetType(), typeof(SqlAuthenticationMethod), null); - } - else - { - try - { - // Enum.ToObject allows only integral and enum values (enums are blocked above), raising ArgumentException for the rest - eValue = (SqlAuthenticationMethod)Enum.ToObject(typeof(SqlAuthenticationMethod), value); - } - catch (ArgumentException e) - { - // to be consistent with the messages we send in case of wrong type usage, replace - // the error with our exception, and keep the original one as inner one for troubleshooting - throw ADP.ConvertFailed(value.GetType(), typeof(SqlAuthenticationMethod), e); - } - } - - // ensure value is in valid range - if (IsValidAuthenticationTypeValue(eValue)) - { - return eValue; - } - else - { - throw ADP.InvalidEnumerationValue(typeof(SqlAuthenticationMethod), (int)eValue); - } - } - } - - /// - /// Convert the provided value to a SqlConnectionColumnEncryptionSetting. - /// - /// - /// - /// - internal static SqlConnectionColumnEncryptionSetting ConvertToColumnEncryptionSetting(string keyword, object value) - { - if (null == value) - { - return DbConnectionStringDefaults.ColumnEncryptionSetting; - } - - string sValue = (value as string); - SqlConnectionColumnEncryptionSetting result; - if (null != sValue) - { - if (TryConvertToColumnEncryptionSetting(sValue, out result)) - { - return result; - } - - // try again after remove leading & trailing whitespaces. - sValue = sValue.Trim(); - if (TryConvertToColumnEncryptionSetting(sValue, out result)) - { - return result; - } - - // string values must be valid - throw ADP.InvalidConnectionOptionValue(keyword); - } - else - { - // the value is not string, try other options - SqlConnectionColumnEncryptionSetting eValue; - - if (value is SqlConnectionColumnEncryptionSetting) - { - // quick path for the most common case - eValue = (SqlConnectionColumnEncryptionSetting)value; - } - else if (value.GetType().IsEnum) - { - // explicitly block scenarios in which user tries to use wrong enum types, like: - // builder["SqlConnectionColumnEncryptionSetting"] = EnvironmentVariableTarget.Process; - // workaround: explicitly cast non-SqlConnectionColumnEncryptionSetting enums to int - throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionColumnEncryptionSetting), null); - } - else - { - try - { - // Enum.ToObject allows only integral and enum values (enums are blocked above), raising ArgumentException for the rest - eValue = (SqlConnectionColumnEncryptionSetting)Enum.ToObject(typeof(SqlConnectionColumnEncryptionSetting), value); - } - catch (ArgumentException e) - { - // to be consistent with the messages we send in case of wrong type usage, replace - // the error with our exception, and keep the original one as inner one for troubleshooting - throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionColumnEncryptionSetting), e); - } - } - - // ensure value is in valid range - if (IsValidColumnEncryptionSetting(eValue)) - { - return eValue; - } - else - { - throw ADP.InvalidEnumerationValue(typeof(SqlConnectionColumnEncryptionSetting), (int)eValue); - } - } - } - - #region <> - - /// - /// Attestation Protocol. - /// - const string AttestationProtocolHGS = "HGS"; - const string AttestationProtocolAAS = "AAS"; -#if ENCLAVE_SIMULATOR - const string AttestationProtocolSIM = "SIM"; -#endif - - /// - /// Convert a string value to the corresponding SqlConnectionAttestationProtocol - /// - /// - /// - /// - internal static bool TryConvertToAttestationProtocol(string value, out SqlConnectionAttestationProtocol result) - { - if (StringComparer.InvariantCultureIgnoreCase.Equals(value, AttestationProtocolHGS)) - { - result = SqlConnectionAttestationProtocol.HGS; - return true; - } - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, AttestationProtocolAAS)) - { - result = SqlConnectionAttestationProtocol.AAS; - return true; - } -#if ENCLAVE_SIMULATOR - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, AttestationProtocolSIM)) - { - result = SqlConnectionAttestationProtocol.SIM; - return true; - } -#endif - else - { - result = DbConnectionStringDefaults.AttestationProtocol; - return false; - } - } - - internal static bool IsValidAttestationProtocol(SqlConnectionAttestationProtocol value) - { -#if ENCLAVE_SIMULATOR - Debug.Assert(Enum.GetNames(typeof(SqlConnectionAttestationProtocol)).Length == 4, "SqlConnectionAttestationProtocol enum has changed, update needed"); - return value == SqlConnectionAttestationProtocol.NotSpecified - || value == SqlConnectionAttestationProtocol.HGS - || value == SqlConnectionAttestationProtocol.AAS - || value == SqlConnectionAttestationProtocol.SIM; -#else - Debug.Assert(Enum.GetNames(typeof(SqlConnectionAttestationProtocol)).Length == 3, "SqlConnectionAttestationProtocol enum has changed, update needed"); - return value == SqlConnectionAttestationProtocol.NotSpecified - || value == SqlConnectionAttestationProtocol.HGS - || value == SqlConnectionAttestationProtocol.AAS; -#endif - } - - internal static string AttestationProtocolToString(SqlConnectionAttestationProtocol value) - { - Debug.Assert(IsValidAttestationProtocol(value), "value is not a valid attestation protocol"); - - switch (value) - { - case SqlConnectionAttestationProtocol.HGS: - return AttestationProtocolHGS; - case SqlConnectionAttestationProtocol.AAS: - return AttestationProtocolAAS; -#if ENCLAVE_SIMULATOR - case SqlConnectionAttestationProtocol.SIM: - return AttestationProtocolSIM; -#endif - default: - return null; - } - } - - internal static SqlConnectionAttestationProtocol ConvertToAttestationProtocol(string keyword, object value) - { - if (null == value) - { - return DbConnectionStringDefaults.AttestationProtocol; - } - - string sValue = (value as string); - SqlConnectionAttestationProtocol result; - - if (null != sValue) - { - // try again after remove leading & trailing whitespaces. - sValue = sValue.Trim(); - if (TryConvertToAttestationProtocol(sValue, out result)) - { - return result; - } - - // string values must be valid - throw ADP.InvalidConnectionOptionValue(keyword); - } - else - { - // the value is not string, try other options - SqlConnectionAttestationProtocol eValue; - - if (value is SqlConnectionAttestationProtocol) - { - eValue = (SqlConnectionAttestationProtocol)value; - } - else if (value.GetType().IsEnum) - { - // explicitly block scenarios in which user tries to use wrong enum types, like: - // builder["SqlConnectionAttestationProtocol"] = EnvironmentVariableTarget.Process; - // workaround: explicitly cast non-SqlConnectionAttestationProtocol enums to int - throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionAttestationProtocol), null); - } - else - { - try - { - // Enum.ToObject allows only integral and enum values (enums are blocked above), raising ArgumentException for the rest - eValue = (SqlConnectionAttestationProtocol)Enum.ToObject(typeof(SqlConnectionAttestationProtocol), value); - } - catch (ArgumentException e) - { - // to be consistent with the messages we send in case of wrong type usage, replace - // the error with our exception, and keep the original one as inner one for troubleshooting - throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionAttestationProtocol), e); - } - } - - if (IsValidAttestationProtocol(eValue)) - { - return eValue; - } - else - { - throw ADP.InvalidEnumerationValue(typeof(SqlConnectionAttestationProtocol), (int)eValue); - } - } - } - - #endregion - - #region <> - /// - /// IP Address Preference. - /// - private readonly static Dictionary s_preferenceNames = new(StringComparer.InvariantCultureIgnoreCase); - - static DbConnectionStringBuilderUtil() - { - foreach (SqlConnectionIPAddressPreference item in Enum.GetValues(typeof(SqlConnectionIPAddressPreference))) - { - s_preferenceNames.Add(item.ToString(), item); - } - } - - /// - /// Convert a string value to the corresponding IPAddressPreference. - /// - /// The string representation of the enumeration name to convert. - /// When this method returns, `result` contains an object of type `SqlConnectionIPAddressPreference` whose value is represented by `value` if the operation succeeds. - /// If the parse operation fails, `result` contains the default value of the `SqlConnectionIPAddressPreference` type. - /// `true` if the value parameter was converted successfully; otherwise, `false`. - internal static bool TryConvertToIPAddressPreference(string value, out SqlConnectionIPAddressPreference result) - { - if (!s_preferenceNames.TryGetValue(value, out result)) - { - result = DbConnectionStringDefaults.IPAddressPreference; - return false; - } - return true; - } - - /// - /// Verifies if the `value` is defined in the expected Enum. - /// - internal static bool IsValidIPAddressPreference(SqlConnectionIPAddressPreference value) - => value == SqlConnectionIPAddressPreference.IPv4First - || value == SqlConnectionIPAddressPreference.IPv6First - || value == SqlConnectionIPAddressPreference.UsePlatformDefault; - - internal static string IPAddressPreferenceToString(SqlConnectionIPAddressPreference value) - => Enum.GetName(typeof(SqlConnectionIPAddressPreference), value); - - internal static SqlConnectionIPAddressPreference ConvertToIPAddressPreference(string keyword, object value) - { - if (value is null) - { - return DbConnectionStringDefaults.IPAddressPreference; // IPv4First - } - - if (value is string sValue) - { - // try again after remove leading & trailing whitespaces. - sValue = sValue.Trim(); - if (TryConvertToIPAddressPreference(sValue, out SqlConnectionIPAddressPreference result)) - { - return result; - } - - // string values must be valid - throw ADP.InvalidConnectionOptionValue(keyword); - } - else - { - // the value is not string, try other options - SqlConnectionIPAddressPreference eValue; - - if (value is SqlConnectionIPAddressPreference preference) - { - eValue = preference; - } - else if (value.GetType().IsEnum) - { - // explicitly block scenarios in which user tries to use wrong enum types, like: - // builder["SqlConnectionIPAddressPreference"] = EnvironmentVariableTarget.Process; - // workaround: explicitly cast non-SqlConnectionIPAddressPreference enums to int - throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionIPAddressPreference), null); - } - else - { - try - { - // Enum.ToObject allows only integral and enum values (enums are blocked above), raising ArgumentException for the rest - eValue = (SqlConnectionIPAddressPreference)Enum.ToObject(typeof(SqlConnectionIPAddressPreference), value); - } - catch (ArgumentException e) - { - // to be consistent with the messages we send in case of wrong type usage, replace - // the error with our exception, and keep the original one as inner one for troubleshooting - throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionIPAddressPreference), e); - } - } - - if (IsValidIPAddressPreference(eValue)) - { - return eValue; - } - else - { - throw ADP.InvalidEnumerationValue(typeof(SqlConnectionIPAddressPreference), (int)eValue); - } - } - } - #endregion - - internal static bool IsValidCertificateValue(string value) - { - return string.IsNullOrEmpty(value) - || value.StartsWith("subject:", StringComparison.OrdinalIgnoreCase) - || value.StartsWith("sha1:", StringComparison.OrdinalIgnoreCase); - } - } - - internal static class DbConnectionStringDefaults - { - // all - // internal const string NamedConnection = ""; - private const string _emptyString = ""; - // Odbc - internal const string Driver = _emptyString; - internal const string Dsn = _emptyString; - - // OleDb - internal const bool AdoNetPooler = false; - internal const string FileName = _emptyString; - internal const int OleDbServices = ~(/*DBPROPVAL_OS_AGR_AFTERSESSION*/0x00000008 | /*DBPROPVAL_OS_CLIENTCURSOR*/0x00000004); // -13 - internal const string Provider = _emptyString; - - // OracleClient - internal const bool Unicode = false; - internal const bool OmitOracleConnectionName = false; - - // SqlClient - internal const ApplicationIntent ApplicationIntent = Microsoft.Data.SqlClient.ApplicationIntent.ReadWrite; - internal const string ApplicationName = "Framework Microsoft SqlClient Data Provider"; - internal const string AttachDBFilename = _emptyString; - internal const int CommandTimeout = 30; - internal const int ConnectTimeout = 15; - internal const bool ConnectionReset = true; - internal const bool ContextConnection = false; - internal const string CurrentLanguage = _emptyString; - internal const string DataSource = _emptyString; - internal const bool Encrypt = false; - internal const bool Enlist = true; - internal const string FailoverPartner = _emptyString; - internal const string InitialCatalog = _emptyString; - internal const bool IntegratedSecurity = false; - internal const int LoadBalanceTimeout = 0; // default of 0 means don't use - internal const bool MultipleActiveResultSets = false; - internal const bool MultiSubnetFailover = false; - internal static readonly bool TransparentNetworkIPResolution = LocalAppContextSwitches.DisableTNIRByDefault ? false : true; - internal const int MaxPoolSize = 100; - internal const int MinPoolSize = 0; - internal const string NetworkLibrary = _emptyString; - internal const int PacketSize = 8000; - internal const string Password = _emptyString; - internal const bool PersistSecurityInfo = false; - internal const bool Pooling = true; - internal const bool TrustServerCertificate = false; - internal const string TypeSystemVersion = "Latest"; - internal const string UserID = _emptyString; - internal const bool UserInstance = false; - internal const bool Replication = false; - internal const string WorkstationID = _emptyString; - internal const string TransactionBinding = "Implicit Unbind"; - internal const int ConnectRetryCount = 1; - internal const int ConnectRetryInterval = 10; - internal static readonly SqlAuthenticationMethod Authentication = SqlAuthenticationMethod.NotSpecified; - internal static readonly SqlConnectionColumnEncryptionSetting ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Disabled; - internal const string EnclaveAttestationUrl = _emptyString; - internal const SqlConnectionAttestationProtocol AttestationProtocol = SqlConnectionAttestationProtocol.NotSpecified; - internal const SqlConnectionIPAddressPreference IPAddressPreference = SqlConnectionIPAddressPreference.IPv4First; - internal const string Certificate = _emptyString; - internal const PoolBlockingPeriod PoolBlockingPeriod = SqlClient.PoolBlockingPeriod.Auto; - } - - internal static class DbConnectionOptionKeywords - { - // Odbc - internal const string Driver = "driver"; - internal const string Pwd = "pwd"; - internal const string UID = "uid"; - - // OleDb - internal const string DataProvider = "data provider"; - internal const string ExtendedProperties = "extended properties"; - internal const string FileName = "file name"; - internal const string Provider = "provider"; - internal const string RemoteProvider = "remote provider"; - - // common keywords (OleDb, OracleClient, SqlClient) - internal const string Password = "password"; - internal const string UserID = "user id"; - } - - internal static class DbConnectionStringKeywords - { - // all - // internal const string NamedConnection = "Named Connection"; - - // Odbc - internal const string Driver = "Driver"; - internal const string Dsn = "Dsn"; - internal const string FileDsn = "FileDsn"; - internal const string SaveFile = "SaveFile"; - - // OleDb - internal const string FileName = "File Name"; - internal const string OleDbServices = "OLE DB Services"; - internal const string Provider = "Provider"; - - // OracleClient - internal const string Unicode = "Unicode"; - internal const string OmitOracleConnectionName = "Omit Oracle Connection Name"; - - // SqlClient - internal const string ApplicationIntent = "Application Intent"; - internal const string ApplicationName = "Application Name"; - internal const string AttachDBFilename = "AttachDbFilename"; - internal const string ConnectTimeout = "Connect Timeout"; - internal const string CommandTimeout = "Command Timeout"; - internal const string ConnectionReset = "Connection Reset"; - internal const string ContextConnection = "Context Connection"; - internal const string CurrentLanguage = "Current Language"; - internal const string Encrypt = "Encrypt"; - internal const string FailoverPartner = "Failover Partner"; - internal const string InitialCatalog = "Initial Catalog"; - internal const string MultipleActiveResultSets = "Multiple Active Result Sets"; - internal const string MultiSubnetFailover = "Multi Subnet Failover"; - internal const string TransparentNetworkIPResolution = "Transparent Network IP Resolution"; - internal const string NetworkLibrary = "Network Library"; - internal const string PacketSize = "Packet Size"; - internal const string Replication = "Replication"; - internal const string TransactionBinding = "Transaction Binding"; - internal const string TrustServerCertificate = "Trust Server Certificate"; - internal const string TypeSystemVersion = "Type System Version"; - internal const string UserInstance = "User Instance"; - internal const string WorkstationID = "Workstation ID"; - internal const string ConnectRetryCount = "Connect Retry Count"; - internal const string ConnectRetryInterval = "Connect Retry Interval"; - internal const string Authentication = "Authentication"; - internal const string Certificate = "Certificate"; - internal const string ColumnEncryptionSetting = "Column Encryption Setting"; - internal const string EnclaveAttestationUrl = "Enclave Attestation Url"; - internal const string AttestationProtocol = "Attestation Protocol"; - internal const string IPAddressPreference = "IP Address Preference"; - internal const string PoolBlockingPeriod = "Pool Blocking Period"; - - // common keywords (OleDb, OracleClient, SqlClient) - internal const string DataSource = "Data Source"; - internal const string IntegratedSecurity = "Integrated Security"; - internal const string Password = "Password"; - internal const string PersistSecurityInfo = "Persist Security Info"; - internal const string UserID = "User ID"; - - // managed pooling (OracleClient, SqlClient) - internal const string Enlist = "Enlist"; - internal const string LoadBalanceTimeout = "Load Balance Timeout"; - internal const string MaxPoolSize = "Max Pool Size"; - internal const string Pooling = "Pooling"; - internal const string MinPoolSize = "Min Pool Size"; - } - - internal static class DbConnectionStringSynonyms - { - //internal const string ApplicationName = APP; - internal const string APP = "app"; - - // internal const string IPAddressPreference = IPADDRESSPREFERENCE; - internal const string IPADDRESSPREFERENCE = "ipaddresspreference"; - - //internal const string ApplicationIntent = APPLICATIONINTENT; - internal const string APPLICATIONINTENT = "applicationintent"; - - //internal const string AttachDBFilename = EXTENDEDPROPERTIES+","+INITIALFILENAME; - internal const string EXTENDEDPROPERTIES = "extended properties"; - internal const string INITIALFILENAME = "initial file name"; - - //internal const string ConnectTimeout = CONNECTIONTIMEOUT+","+TIMEOUT; - internal const string CONNECTIONTIMEOUT = "connection timeout"; - internal const string TIMEOUT = "timeout"; - - //internal const string ConnectRetryCount = CONNECTRETRYCOUNT; - internal const string CONNECTRETRYCOUNT = "connectretrycount"; - - //internal const string ConnectRetryInterval = CONNECTRETRYINTERVAL; - internal const string CONNECTRETRYINTERVAL = "connectretryinterval"; - - //internal const string CurrentLanguage = LANGUAGE; - internal const string LANGUAGE = "language"; - - //internal const string OraDataSource = SERVER; - //internal const string SqlDataSource = ADDR+","+ADDRESS+","+SERVER+","+NETWORKADDRESS; - internal const string ADDR = "addr"; - internal const string ADDRESS = "address"; - internal const string SERVER = "server"; - internal const string NETWORKADDRESS = "network address"; - - //internal const string InitialCatalog = DATABASE; - internal const string DATABASE = "database"; - - //internal const string IntegratedSecurity = TRUSTEDCONNECTION; - internal const string TRUSTEDCONNECTION = "trusted_connection"; // underscore introduced in everett - - //internal const string LoadBalanceTimeout = ConnectionLifetime; - internal const string ConnectionLifetime = "connection lifetime"; - - //internal const string MultipleActiveResultSets = MULTIPLEACTIVERESULTSETS; - internal const string MULTIPLEACTIVERESULTSETS = "multipleactiveresultsets"; - - //internal const string MultiSubnetFailover = MULTISUBNETFAILOVER; - internal const string MULTISUBNETFAILOVER = "multisubnetfailover"; - - //internal const string NetworkLibrary = NET+","+NETWORK; - internal const string NET = "net"; - internal const string NETWORK = "network"; - - //internal const string PoolBlockingPeriod = POOLBLOCKINGPERIOD; - internal const string POOLBLOCKINGPERIOD = "poolblockingperiod"; - - internal const string WorkaroundOracleBug914652 = "Workaround Oracle Bug 914652"; - - //internal const string Password = Pwd; - internal const string Pwd = "pwd"; - - //internal const string PersistSecurityInfo = PERSISTSECURITYINFO; - internal const string PERSISTSECURITYINFO = "persistsecurityinfo"; - - //internal const string TrustServerCertificate = TRUSTSERVERCERTIFICATE; - internal const string TRUSTSERVERCERTIFICATE = "trustservercertificate"; - - //internal const string TransparentNetworkIPResolution = TRANSPARENTNETWORKIPRESOLUTION; - internal const string TRANSPARENTNETWORKIPRESOLUTION = "transparentnetworkipresolution"; - - //internal const string UserID = UID+","+User; - internal const string UID = "uid"; - internal const string User = "user"; - - //internal const string WorkstationID = WSID; - internal const string WSID = "wsid"; - } -} diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/SqlDataRecord.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/SqlDataRecord.cs deleted file mode 100644 index 88db0bb49b..0000000000 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/SqlDataRecord.cs +++ /dev/null @@ -1,541 +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.Data; -using System.Data.SqlTypes; -using System.Diagnostics; -using Microsoft.Data.Common; -using Microsoft.Data.ProviderBase; - -namespace Microsoft.Data.SqlClient.Server -{ - /// - public class SqlDataRecord : IDataRecord - { - private readonly SmiRecordBuffer _recordBuffer; - private readonly SmiContext _recordContext; - private readonly SmiExtendedMetaData[] _columnSmiMetaData; - private readonly SmiEventSink_Default _eventSink; - private readonly SqlMetaData[] _columnMetaData; - private readonly bool _usesStringStorageForXml; - private FieldNameLookup _fieldNameLookup; - - static readonly SmiMetaData s_maxNVarCharForXml = new SmiMetaData( - SqlDbType.NVarChar, - SmiMetaData.UnlimitedMaxLengthIndicator, - SmiMetaData.DefaultNVarChar_NoCollation.Precision, - SmiMetaData.DefaultNVarChar_NoCollation.Scale, - SmiMetaData.DefaultNVarChar.LocaleId, - SmiMetaData.DefaultNVarChar.CompareOptions, - userDefinedType: null - ); - - /// - public virtual int FieldCount => _columnMetaData.Length; - - /// - public virtual string GetName(int ordinal) => GetSqlMetaData(ordinal).Name; - - /// - public virtual string GetDataTypeName(int ordinal) - { - SqlMetaData metaData = GetSqlMetaData(ordinal); - if (metaData.SqlDbType == SqlDbType.Udt) - { - return metaData.UdtTypeName; - } - else - { - return MetaType.GetMetaTypeFromSqlDbType(metaData.SqlDbType, false).TypeName; - } - } - - /// - public virtual Type GetFieldType(int ordinal) - { - SqlMetaData md = GetSqlMetaData(ordinal); - if (md.SqlDbType == SqlDbType.Udt) - { - return md.Type; - } - else - { - return MetaType.GetMetaTypeFromSqlDbType(md.SqlDbType, false).ClassType; - } - } - - /// - public virtual object GetValue(int ordinal) - { - SmiMetaData metaData = GetSmiMetaData(ordinal); - if (SmiVersion >= SmiContextFactory.KatmaiVersion) - { - return ValueUtilsSmi.GetValue200(_eventSink, _recordBuffer, ordinal, metaData, _recordContext); - } - else - { - return ValueUtilsSmi.GetValue(_eventSink, _recordBuffer, ordinal, metaData, _recordContext); - } - } - - /// - public virtual int GetValues(object[] values) - { - if (values == null) - { - throw ADP.ArgumentNull(nameof(values)); - } - - int copyLength = (values.Length < FieldCount) ? values.Length : FieldCount; - for (int i = 0; i < copyLength; i++) - { - values[i] = GetValue(i); - } - - return copyLength; - } - - /// - public virtual int GetOrdinal(string name) - { - if (null == _fieldNameLookup) - { - string[] names = new string[FieldCount]; - for (int i = 0; i < names.Length; i++) - { - names[i] = GetSqlMetaData(i).Name; - } - - _fieldNameLookup = new FieldNameLookup(names, -1); - } - - return _fieldNameLookup.GetOrdinal(name); - } - - /// - public virtual object this[int ordinal] => GetValue(ordinal); - - /// - public virtual object this[string name] => GetValue(GetOrdinal(name)); - - /// - public virtual bool GetBoolean(int ordinal) => ValueUtilsSmi.GetBoolean(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual byte GetByte(int ordinal) => ValueUtilsSmi.GetByte(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual long GetBytes(int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length) - { - return ValueUtilsSmi.GetBytes(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), fieldOffset, buffer, bufferOffset, length, throwOnNull: true); - } - - /// - public virtual char GetChar(int ordinal) => throw ADP.NotSupported(); - - /// - public virtual long GetChars(int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length) - { - return ValueUtilsSmi.GetChars(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), fieldOffset, buffer, bufferOffset, length); - } - - /// - public virtual Guid GetGuid(int ordinal) => ValueUtilsSmi.GetGuid(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual short GetInt16(int ordinal) => ValueUtilsSmi.GetInt16(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual int GetInt32(int ordinal) => ValueUtilsSmi.GetInt32(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual long GetInt64(int ordinal) => ValueUtilsSmi.GetInt64(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual float GetFloat(int ordinal) => ValueUtilsSmi.GetSingle(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual double GetDouble(int ordinal) => ValueUtilsSmi.GetDouble(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual string GetString(int ordinal) - { - SmiMetaData colMeta = GetSmiMetaData(ordinal); - if (_usesStringStorageForXml && colMeta.SqlDbType == SqlDbType.Xml) - { - return ValueUtilsSmi.GetString(_eventSink, _recordBuffer, ordinal, s_maxNVarCharForXml); - } - else - { - return ValueUtilsSmi.GetString(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - } - } - - /// - public virtual decimal GetDecimal(int ordinal) => ValueUtilsSmi.GetDecimal(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual DateTime GetDateTime(int ordinal) => ValueUtilsSmi.GetDateTime(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual DateTimeOffset GetDateTimeOffset(int ordinal) => ValueUtilsSmi.GetDateTimeOffset(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual TimeSpan GetTimeSpan(int ordinal) => ValueUtilsSmi.GetTimeSpan(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual bool IsDBNull(int ordinal) - { - ThrowIfInvalidOrdinal(ordinal); - return ValueUtilsSmi.IsDBNull(_eventSink, _recordBuffer, ordinal); - } - - /// - // ISqlRecord implementation - public virtual SqlMetaData GetSqlMetaData(int ordinal) - { - ThrowIfInvalidOrdinal(ordinal); - return _columnMetaData[ordinal]; - } - - /// - public virtual Type GetSqlFieldType(int ordinal) - { - SqlMetaData md = GetSqlMetaData(ordinal); - return MetaType.GetMetaTypeFromSqlDbType(md.SqlDbType, false).SqlType; - } - - /// - public virtual object GetSqlValue(int ordinal) - { - SmiMetaData metaData = GetSmiMetaData(ordinal); - if (SmiVersion >= SmiContextFactory.KatmaiVersion) - { - return ValueUtilsSmi.GetSqlValue200(_eventSink, _recordBuffer, ordinal, metaData, _recordContext); - } - return ValueUtilsSmi.GetSqlValue(_eventSink, _recordBuffer, ordinal, metaData, _recordContext); - } - - /// - public virtual int GetSqlValues(object[] values) - { - if (values == null) - { - throw ADP.ArgumentNull(nameof(values)); - } - - int copyLength = (values.Length < FieldCount) ? values.Length : FieldCount; - for (int i = 0; i < copyLength; i++) - { - values[i] = GetSqlValue(i); - } - - return copyLength; - } - - /// - public virtual SqlBinary GetSqlBinary(int ordinal) => ValueUtilsSmi.GetSqlBinary(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlBytes GetSqlBytes(int ordinal) => ValueUtilsSmi.GetSqlBytes(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), _recordContext); - - /// - public virtual SqlXml GetSqlXml(int ordinal) => ValueUtilsSmi.GetSqlXml(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), _recordContext); - - /// - public virtual SqlBoolean GetSqlBoolean(int ordinal) => ValueUtilsSmi.GetSqlBoolean(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlByte GetSqlByte(int ordinal) => ValueUtilsSmi.GetSqlByte(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlChars GetSqlChars(int ordinal) => ValueUtilsSmi.GetSqlChars(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), _recordContext); - - /// - public virtual SqlInt16 GetSqlInt16(int ordinal) => ValueUtilsSmi.GetSqlInt16(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlInt32 GetSqlInt32(int ordinal) => ValueUtilsSmi.GetSqlInt32(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlInt64 GetSqlInt64(int ordinal) => ValueUtilsSmi.GetSqlInt64(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlSingle GetSqlSingle(int ordinal) => ValueUtilsSmi.GetSqlSingle(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlDouble GetSqlDouble(int ordinal) => ValueUtilsSmi.GetSqlDouble(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlMoney GetSqlMoney(int ordinal) => ValueUtilsSmi.GetSqlMoney(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlDateTime GetSqlDateTime(int ordinal) => ValueUtilsSmi.GetSqlDateTime(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlDecimal GetSqlDecimal(int ordinal) => ValueUtilsSmi.GetSqlDecimal(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlString GetSqlString(int ordinal) => ValueUtilsSmi.GetSqlString(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - public virtual SqlGuid GetSqlGuid(int ordinal) => ValueUtilsSmi.GetSqlGuid(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); - - /// - // ISqlUpdateableRecord Implementation - public virtual int SetValues(params object[] values) - { - if (values == null) - { - throw ADP.ArgumentNull(nameof(values)); - } - - // Allow values array longer than FieldCount, just ignore the extra cells. - int copyLength = (values.Length > FieldCount) ? FieldCount : values.Length; - - ExtendedClrTypeCode[] typeCodes = new ExtendedClrTypeCode[copyLength]; - - // Verify all data values as acceptable before changing current state. - for (int i = 0; i < copyLength; i++) - { - SqlMetaData metaData = GetSqlMetaData(i); - typeCodes[i] = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType( - metaData.SqlDbType, - isMultiValued: false, - values[i], - metaData.Type, - SmiVersion - ); - if (typeCodes[i] == ExtendedClrTypeCode.Invalid) - { - throw ADP.InvalidCast(); - } - } - - // Now move the data (it'll only throw if someone plays with the values array between - // the validation loop and here, or if an invalid UDT was sent). - for (int i = 0; i < copyLength; i++) - { - if (SmiVersion >= SmiContextFactory.KatmaiVersion) - { - ValueUtilsSmi.SetCompatibleValueV200(_eventSink, _recordBuffer, i, GetSmiMetaData(i), values[i], typeCodes[i], offset: 0, length: 0, peekAhead: null); - } - else - { - ValueUtilsSmi.SetCompatibleValue(_eventSink, _recordBuffer, i, GetSmiMetaData(i), values[i], typeCodes[i], offset: 0); - } - } - - return copyLength; - } - - /// - public virtual void SetValue(int ordinal, object value) - { - SqlMetaData metaData = GetSqlMetaData(ordinal); - ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType( - metaData.SqlDbType, - isMultiValued:false, - value, - metaData.Type, - SmiVersion - ); - if (typeCode == ExtendedClrTypeCode.Invalid) - { - throw ADP.InvalidCast(); - } - - if (SmiVersion >= SmiContextFactory.KatmaiVersion) - { - ValueUtilsSmi.SetCompatibleValueV200(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value, typeCode, offset: 0, length: 0, peekAhead: null); - } - else - { - ValueUtilsSmi.SetCompatibleValue(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value, typeCode, offset: 0); - } - } - - /// - public virtual void SetBoolean(int ordinal, bool value) => ValueUtilsSmi.SetBoolean(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetByte(int ordinal, byte value) => ValueUtilsSmi.SetByte(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetBytes(int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length) => ValueUtilsSmi.SetBytes(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), fieldOffset, buffer, bufferOffset, length); - - /// - public virtual void SetChar(int ordinal, char value) => throw ADP.NotSupported(); - - /// - public virtual void SetChars(int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length) => ValueUtilsSmi.SetChars(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), fieldOffset, buffer, bufferOffset, length); - - /// - public virtual void SetInt16(int ordinal, short value) => ValueUtilsSmi.SetInt16(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetInt32(int ordinal, int value) => ValueUtilsSmi.SetInt32(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetInt64(int ordinal, long value) => ValueUtilsSmi.SetInt64(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetFloat(int ordinal, float value) => ValueUtilsSmi.SetSingle(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - /// - public virtual void SetDouble(int ordinal, double value) => ValueUtilsSmi.SetDouble(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetString(int ordinal, string value) => ValueUtilsSmi.SetString(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetDecimal(int ordinal, decimal value) => ValueUtilsSmi.SetDecimal(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetDateTime(int ordinal, DateTime value) => ValueUtilsSmi.SetDateTime(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetTimeSpan(int ordinal, TimeSpan value) => ValueUtilsSmi.SetTimeSpan(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value, SmiVersion >= SmiContextFactory.KatmaiVersion); - - /// - public virtual void SetDateTimeOffset(int ordinal, DateTimeOffset value) => ValueUtilsSmi.SetDateTimeOffset(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value, SmiVersion >= SmiContextFactory.KatmaiVersion); - - /// - public virtual void SetDBNull(int ordinal) - { - ThrowIfInvalidOrdinal(ordinal); - ValueUtilsSmi.SetDBNull(_eventSink, _recordBuffer, ordinal, true); - } - - /// - public virtual void SetGuid(int ordinal, Guid value) => ValueUtilsSmi.SetGuid(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlBoolean(int ordinal, SqlBoolean value) => ValueUtilsSmi.SetSqlBoolean(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlByte(int ordinal, SqlByte value) => ValueUtilsSmi.SetSqlByte(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlInt16(int ordinal, SqlInt16 value) => ValueUtilsSmi.SetSqlInt16(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlInt32(int ordinal, SqlInt32 value) => ValueUtilsSmi.SetSqlInt32(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlInt64(int ordinal, SqlInt64 value) => ValueUtilsSmi.SetSqlInt64(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlSingle(int ordinal, SqlSingle value) => ValueUtilsSmi.SetSqlSingle(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlDouble(int ordinal, SqlDouble value) => ValueUtilsSmi.SetSqlDouble(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlMoney(int ordinal, SqlMoney value) => ValueUtilsSmi.SetSqlMoney(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlDateTime(int ordinal, SqlDateTime value) => ValueUtilsSmi.SetSqlDateTime(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlXml(int ordinal, SqlXml value) => ValueUtilsSmi.SetSqlXml(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlDecimal(int ordinal, SqlDecimal value) => ValueUtilsSmi.SetSqlDecimal(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlString(int ordinal, SqlString value) => ValueUtilsSmi.SetSqlString(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlBinary(int ordinal, SqlBinary value) => ValueUtilsSmi.SetSqlBinary(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlGuid(int ordinal, SqlGuid value) => ValueUtilsSmi.SetSqlGuid(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlChars(int ordinal, SqlChars value) => ValueUtilsSmi.SetSqlChars(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - /// - public virtual void SetSqlBytes(int ordinal, SqlBytes value) => ValueUtilsSmi.SetSqlBytes(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); - - // SqlDataRecord public API - /// - public SqlDataRecord(params SqlMetaData[] metaData) - { - // Initial consistency check - if (null == metaData) - { - throw ADP.ArgumentNull(nameof(metaData)); - } - - _columnMetaData = new SqlMetaData[metaData.Length]; - _columnSmiMetaData = new SmiExtendedMetaData[metaData.Length]; - ulong smiVersion = SmiVersion; - for (int i = 0; i < _columnSmiMetaData.Length; i++) - { - if (metaData[i] == null) - { - throw ADP.ArgumentNull($"{nameof(metaData)}[{i}]"); - } - _columnMetaData[i] = metaData[i]; - _columnSmiMetaData[i] = MetaDataUtilsSmi.SqlMetaDataToSmiExtendedMetaData(_columnMetaData[i]); - if (!MetaDataUtilsSmi.IsValidForSmiVersion(_columnSmiMetaData[i], smiVersion)) - { - throw ADP.VersionDoesNotSupportDataType(_columnSmiMetaData[i].TypeName); - } - } - - _eventSink = new SmiEventSink_Default(); - - if (InOutOfProcHelper.InProc) - { - _recordContext = SmiContextFactory.Instance.GetCurrentContext(); - _recordBuffer = _recordContext.CreateRecordBuffer(_columnSmiMetaData, _eventSink); - _usesStringStorageForXml = false; - } - else - { - _recordContext = null; - _recordBuffer = new MemoryRecordBuffer(_columnSmiMetaData); - _usesStringStorageForXml = true; - } - _eventSink.ProcessMessagesAndThrow(); - } - - // - // SqlDataRecord private members - // - internal SmiRecordBuffer RecordBuffer => _recordBuffer; - - internal SmiContext RecordContext => _recordContext; - - private ulong SmiVersion => InOutOfProcHelper.InProc ? SmiContextFactory.Instance.NegotiatedSmiVersion : SmiContextFactory.LatestVersion; - - internal SqlMetaData[] InternalGetMetaData() - { - return _columnMetaData; - } - - internal SmiExtendedMetaData[] InternalGetSmiMetaData() => _columnSmiMetaData; - - internal SmiExtendedMetaData GetSmiMetaData(int ordinal) - { - ThrowIfInvalidOrdinal(ordinal); - return _columnSmiMetaData[ordinal]; - } - - internal void ThrowIfInvalidOrdinal(int ordinal) - { - if (0 > ordinal || FieldCount <= ordinal) - { - throw ADP.IndexOutOfRange(ordinal); - } - } - - /// - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - IDataReader System.Data.IDataRecord.GetData(int ordinal) => throw ADP.NotSupported(); - } -} - diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs deleted file mode 100644 index 28bc1ae376..0000000000 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs +++ /dev/null @@ -1,4420 +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.Data; -using System.Data.Common; -using System.Data.SqlTypes; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Reflection; -using System.Xml; -using Microsoft.Data.Common; -using Microsoft.Data.SqlTypes; - -namespace Microsoft.Data.SqlClient.Server -{ - // Utilities for manipulating values with the Smi interface. - // - // THIS CLASS IS BUILT ON TOP OF THE SMI INTERFACE -- SMI SHOULD NOT DEPEND ON IT! - // - // These are all based off of knowing the clr type of the value - // as an ExtendedClrTypeCode enum for rapid access (lookup in static array is best, if possible). - internal static class ValueUtilsSmi - { - private const int __maxByteChunkSize = TdsEnums.MAXSIZE; - private const int __maxCharChunkSize = TdsEnums.MAXSIZE / sizeof(char); - private const int NoLengthLimit = (int)SmiMetaData.UnlimitedMaxLengthIndicator; // make sure we use the same constant - - // Constants - private const int constBinBufferSize = 4096; // Size of the buffer used to read input parameter of type Stream - private const int constTextBufferSize = 4096; // Size of the buffer (in chars) user to read input parameter of type TextReader - - // - // User-visible semantics-laden Getter/Setter support methods - // These methods implement common semantics for getters & setters - // All access to underlying Smi getters/setters must validate parameters - // in these methods - // - - // The idea for the getters is that there are two types associated with the field/column, - // the one the user asks for (implicitly via a strongly-typed getter) and the one the data - // is stored in (SmiMetaData). - // When a strong getter is invoked, we try one of two ways to get the value - // 1) go directly to the source for the requested type if possible - // 2) instantiate the value based on the stored type (GetValue), then ask the Clr - // to convert. - internal static bool IsDBNull(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - return IsDBNull_Unchecked(sink, getters, ordinal); - } - - internal static bool GetBoolean(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Boolean)) - { - return GetBoolean_Unchecked(sink, getters, ordinal); - } - - object result = GetValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (bool)result; - } - - internal static byte GetByte(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Byte)) - { - return GetByte_Unchecked(sink, getters, ordinal); - } - object result = GetValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (byte)result; - } - - private static long GetBytesConversion(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, long fieldOffset, byte[] buffer, int bufferOffset, int length, bool throwOnNull) - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - SqlBinary value = (SqlBinary)obj; - - if (value.IsNull) - { - if (throwOnNull) - { - throw SQL.SqlNullValue(); - } - else - { - // return zero length in any case - return 0; - } - } - - if (null == buffer) - { - return value.Length; - } - - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength * sizeof(char), value.Length, - fieldOffset, buffer.Length, bufferOffset, length); - Array.Copy(value.Value, checked((int)fieldOffset), buffer, bufferOffset, length); - return length; - } - - internal static long GetBytes(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiExtendedMetaData metaData, long fieldOffset, byte[] buffer, int bufferOffset, int length, bool throwOnNull) - { - // Additional exclusions not caught by GetBytesInternal - if ((SmiMetaData.UnlimitedMaxLengthIndicator != metaData.MaxLength && - (SqlDbType.VarChar == metaData.SqlDbType || - SqlDbType.NVarChar == metaData.SqlDbType || - SqlDbType.Char == metaData.SqlDbType || - SqlDbType.NChar == metaData.SqlDbType)) || - SqlDbType.Xml == metaData.SqlDbType) - { - throw SQL.NonBlobColumn(metaData.Name); - } - else - { - return GetBytesInternal(sink, getters, ordinal, metaData, fieldOffset, buffer, bufferOffset, length, throwOnNull); - } - } - - internal static long GetBytesInternal(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, long fieldOffset, byte[] buffer, int bufferOffset, int length, bool throwOnNull) - { - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.ByteArray)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - if (throwOnNull) - { - throw SQL.SqlNullValue(); - } - else - { - // check user's parameters for validity against a zero-length value - CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, 0, fieldOffset, buffer.Length, bufferOffset, length); - - // return zero length in any case - return 0; - } - } - long actualLength = GetBytesLength_Unchecked(sink, getters, ordinal); - if (null == buffer) - { - return actualLength; - } - if (MetaDataUtilsSmi.IsCharOrXmlType(metaData.SqlDbType)) - { - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength * sizeof(char), actualLength, - fieldOffset, buffer.Length, bufferOffset, length); - } - else - { - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, actualLength, fieldOffset, buffer.Length, bufferOffset, length); - } - Debug.Assert(length >= 0, "Invalid CheckXetParameters return length!"); - if (length > 0) - { - length = GetBytes_Unchecked(sink, getters, ordinal, fieldOffset, buffer, bufferOffset, length); - } - return length; - } - - return GetBytesConversion(sink, getters, ordinal, metaData, fieldOffset, buffer, bufferOffset, length, throwOnNull); - } - - internal static long GetChars(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, long fieldOffset, char[] buffer, int bufferOffset, int length) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.CharArray)) - { - long actualLength = GetCharsLength_Unchecked(sink, getters, ordinal); - if (null == buffer) - { - return actualLength; - } - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, actualLength, fieldOffset, buffer.Length, bufferOffset, length); - Debug.Assert(length >= 0, "Buffer.Length was invalid!"); - if (length > 0) - { - length = GetChars_Unchecked(sink, getters, ordinal, fieldOffset, buffer, bufferOffset, length); - } - return length; - } - - string value = ((string)GetValue(sink, getters, ordinal, metaData, null)); - if (null == value) - { - throw ADP.InvalidCast(); - } - if (null == buffer) - { - return value.Length; - } - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength * sizeof(char), value.Length, - fieldOffset, buffer.Length, bufferOffset, length); - value.CopyTo(checked((int)fieldOffset), buffer, bufferOffset, length); - return length; - } - - internal static DateTime GetDateTime(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.DateTime)) - { - return GetDateTime_Unchecked(sink, getters, ordinal); - } - object result = GetValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (DateTime)result; - } - - // calling GetDateTimeOffset on possibly v100 SMI - internal static DateTimeOffset GetDateTimeOffset(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, bool gettersSupportKatmaiDateTime) - { - if (gettersSupportKatmaiDateTime) - { - return GetDateTimeOffset(sink, (SmiTypedGetterSetter)getters, ordinal, metaData); - } - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - object result = GetValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (DateTimeOffset)result; - } - - // dealing with v200 SMI - internal static DateTimeOffset GetDateTimeOffset(SmiEventSink_Default sink, SmiTypedGetterSetter getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.DateTimeOffset)) - { - return GetDateTimeOffset_Unchecked(sink, getters, ordinal); - } - return (DateTimeOffset)GetValue200(sink, getters, ordinal, metaData, null); - } - - internal static decimal GetDecimal(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Decimal)) - { - return GetDecimal_PossiblyMoney(sink, getters, ordinal, metaData); - } - object result = GetValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (decimal)result; - } - - internal static double GetDouble(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Double)) - { - return GetDouble_Unchecked(sink, getters, ordinal); - } - object result = GetValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (double)result; - } - - internal static Guid GetGuid(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Guid)) - { - return GetGuid_Unchecked(sink, getters, ordinal); - } - object result = GetValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (Guid)result; - } - - internal static short GetInt16(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Int16)) - { - return GetInt16_Unchecked(sink, getters, ordinal); - } - object obj = GetValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - return (short)obj; - } - - internal static int GetInt32(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Int32)) - { - return GetInt32_Unchecked(sink, getters, ordinal); - } - object result = GetValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (int)result; - } - - internal static long GetInt64(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Int64)) - { - return GetInt64_Unchecked(sink, getters, ordinal); - } - object result = GetValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (long)result; - } - - internal static float GetSingle(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Single)) - { - return GetSingle_Unchecked(sink, getters, ordinal); - } - object result = GetValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (float)result; - } - - internal static SqlBinary GetSqlBinary(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlBinary)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - return SqlBinary.Null; - } - return GetSqlBinary_Unchecked(sink, getters, ordinal); - } - object result = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (SqlBinary)result; - } - - internal static SqlBoolean GetSqlBoolean(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlBoolean)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - return SqlBoolean.Null; - } - return new SqlBoolean(GetBoolean_Unchecked(sink, getters, ordinal)); - } - object result = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (SqlBoolean)result; - } - - internal static SqlByte GetSqlByte(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlByte)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - return SqlByte.Null; - } - return new SqlByte(GetByte_Unchecked(sink, getters, ordinal)); - } - object result = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == result) - { - throw ADP.InvalidCast(); - } - return (SqlByte)result; - } - - internal static SqlBytes GetSqlBytes(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, SmiContext context) - { - SqlBytes result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlBytes)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlBytes.Null; - } - else - { - long length = GetBytesLength_Unchecked(sink, getters, ordinal); - if (0 <= length && length < __maxByteChunkSize) - { - byte[] byteBuffer = GetByteArray_Unchecked(sink, getters, ordinal); - result = new SqlBytes(byteBuffer); - } - else - { - Stream s = new SmiGettersStream(sink, getters, ordinal, metaData); - s = CopyIntoNewSmiScratchStream(s, sink, context); - result = new SqlBytes(s); - } - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - SqlBinary binaryVal = (SqlBinary)obj; - if (binaryVal.IsNull) - { - result = SqlBytes.Null; - } - else - { - result = new SqlBytes(binaryVal.Value); - } - } - - return result; - } - - internal static SqlChars GetSqlChars(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, SmiContext context) - { - SqlChars result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlChars)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlChars.Null; - } - else - { - long length = GetCharsLength_Unchecked(sink, getters, ordinal); - if (length < __maxCharChunkSize || !InOutOfProcHelper.InProc) - { - char[] charBuffer = GetCharArray_Unchecked(sink, getters, ordinal); - result = new SqlChars(charBuffer); - } - else - { // InProc only - Stream s = new SmiGettersStream(sink, getters, ordinal, metaData); - SqlStreamChars sc = CopyIntoNewSmiScratchStreamChars(s, sink, context); - - Type SqlCharsType = (typeof(SqlChars)); - Type[] argTypes = new Type[] { typeof(SqlStreamChars) }; - SqlChars SqlCharsInstance = (SqlChars)SqlCharsType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, - null, argTypes, null).Invoke(new Object[] { sc }); - result = SqlCharsInstance; - } - } - } - else - { - SqlString stringValue; - if (SqlDbType.Xml == metaData.SqlDbType) - { - SqlXml xmlValue = GetSqlXml_Unchecked(sink, getters, ordinal, null); - - if (xmlValue.IsNull) - { - result = SqlChars.Null; - } - else - { - result = new SqlChars(xmlValue.Value.ToCharArray()); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - stringValue = (SqlString)obj; - - if (stringValue.IsNull) - { - result = SqlChars.Null; - } - else - { - result = new SqlChars(stringValue.Value.ToCharArray()); - } - } - } - - return result; - } - - internal static SqlDateTime GetSqlDateTime(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - SqlDateTime result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlDateTime)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlDateTime.Null; - } - else - { - DateTime temp = GetDateTime_Unchecked(sink, getters, ordinal); - result = new SqlDateTime(temp); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - result = (SqlDateTime)obj; - } - - return result; - } - - internal static SqlDecimal GetSqlDecimal(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - SqlDecimal result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlDecimal)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlDecimal.Null; - } - else - { - result = GetSqlDecimal_Unchecked(sink, getters, ordinal); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - result = (SqlDecimal)obj; - } - - return result; - } - - internal static SqlDouble GetSqlDouble(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - SqlDouble result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlDouble)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlDouble.Null; - } - else - { - double temp = GetDouble_Unchecked(sink, getters, ordinal); - result = new SqlDouble(temp); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - result = (SqlDouble)obj; - } - - return result; - } - - internal static SqlGuid GetSqlGuid(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - SqlGuid result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlGuid)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlGuid.Null; - } - else - { - Guid temp = GetGuid_Unchecked(sink, getters, ordinal); - result = new SqlGuid(temp); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - result = (SqlGuid)obj; - } - - return result; - } - - internal static SqlInt16 GetSqlInt16(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - SqlInt16 result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlInt16)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlInt16.Null; - } - else - { - short temp = GetInt16_Unchecked(sink, getters, ordinal); - result = new SqlInt16(temp); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - result = (SqlInt16)obj; - } - - return result; - } - - internal static SqlInt32 GetSqlInt32(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - SqlInt32 result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlInt32)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlInt32.Null; - } - else - { - int temp = GetInt32_Unchecked(sink, getters, ordinal); - result = new SqlInt32(temp); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - result = (SqlInt32)obj; - } - return result; - } - - internal static SqlInt64 GetSqlInt64(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - SqlInt64 result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlInt64)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlInt64.Null; - } - else - { - long temp = GetInt64_Unchecked(sink, getters, ordinal); - result = new SqlInt64(temp); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - result = (SqlInt64)obj; - } - - return result; - } - - internal static SqlMoney GetSqlMoney(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - SqlMoney result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlMoney)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlMoney.Null; - } - else - { - result = GetSqlMoney_Unchecked(sink, getters, ordinal); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - result = (SqlMoney)obj; - } - - return result; - } - - internal static SqlSingle GetSqlSingle(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - SqlSingle result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlSingle)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlSingle.Null; - } - else - { - float temp = GetSingle_Unchecked(sink, getters, ordinal); - result = new SqlSingle(temp); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - result = (SqlSingle)obj; - } - - return result; - } - - internal static SqlString GetSqlString(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - SqlString result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlString)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlString.Null; - } - else - { - string temp = GetString_Unchecked(sink, getters, ordinal); - result = new SqlString(temp); - } - } - else if (SqlDbType.Xml == metaData.SqlDbType) - { - SqlXml xmlValue = GetSqlXml_Unchecked(sink, getters, ordinal, null); - - if (xmlValue.IsNull) - { - result = SqlString.Null; - } - else - { - result = new SqlString(xmlValue.Value); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - result = (SqlString)obj; - } - - return result; - } - - internal static SqlXml GetSqlXml(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, SmiContext context) - { - SqlXml result; - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlXml)) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = SqlXml.Null; - } - else - { - result = GetSqlXml_Unchecked(sink, getters, ordinal, context); - } - } - else - { - object obj = GetSqlValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - result = (SqlXml)obj; - } - - return result; - } - - internal static string GetString(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.String)) - { - return GetString_Unchecked(sink, getters, ordinal); - } - object obj = GetValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - return (string)obj; - } - - internal static SqlSequentialStreamSmi GetSequentialStream(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, bool bypassTypeCheck = false) - { - Debug.Assert(!ValueUtilsSmi.IsDBNull_Unchecked(sink, getters, ordinal), "Should not try to get a SqlSequentialStreamSmi on a null column"); - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if ((!bypassTypeCheck) && (!CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Stream))) - { - throw ADP.InvalidCast(); - } - - // This will advance the column to ordinal - long length = GetBytesLength_Unchecked(sink, getters, ordinal); - return new SqlSequentialStreamSmi(sink, getters, ordinal, length); - } - - internal static SqlSequentialTextReaderSmi GetSequentialTextReader(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - Debug.Assert(!ValueUtilsSmi.IsDBNull_Unchecked(sink, getters, ordinal), "Should not try to get a SqlSequentialTextReaderSmi on a null column"); - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (!CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.TextReader)) - { - throw ADP.InvalidCast(); - } - - // This will advance the column to ordinal - long length = GetCharsLength_Unchecked(sink, getters, ordinal); - return new SqlSequentialTextReaderSmi(sink, getters, ordinal, length); - } - - internal static Stream GetStream(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, bool bypassTypeCheck = false) - { - bool isDbNull = ValueUtilsSmi.IsDBNull_Unchecked(sink, getters, ordinal); - - // If a sql_variant, get the internal type - if (!bypassTypeCheck) - { - if ((!isDbNull) && (metaData.SqlDbType == SqlDbType.Variant)) - { - metaData = getters.GetVariantType(sink, ordinal); - } - // If the SqlDbType is still variant, then it must contain null, so don't throw InvalidCast - if ((metaData.SqlDbType != SqlDbType.Variant) && (!CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Stream))) - { - throw ADP.InvalidCast(); - } - } - - byte[] data; - if (isDbNull) - { - // "null" stream - data = new byte[0]; - } - else - { - // Read all data - data = GetByteArray_Unchecked(sink, getters, ordinal); - } - - // Wrap data in pre-built object - return new MemoryStream(data, writable: false); - } - - internal static TextReader GetTextReader(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - bool isDbNull = ValueUtilsSmi.IsDBNull_Unchecked(sink, getters, ordinal); - - // If a sql_variant, get the internal type - if ((!isDbNull) && (metaData.SqlDbType == SqlDbType.Variant)) - { - metaData = getters.GetVariantType(sink, ordinal); - } - // If the SqlDbType is still variant, then it must contain null, so don't throw InvalidCast - if ((metaData.SqlDbType != SqlDbType.Variant) && (!CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.TextReader))) - { - throw ADP.InvalidCast(); - } - - string data; - if (isDbNull) - { - // "null" textreader - data = string.Empty; - } - else - { - // Read all data - data = GetString_Unchecked(sink, getters, ordinal); - } - - // Wrap in pre-built object - return new StringReader(data); - } - - // calling GetTimeSpan on possibly v100 SMI - internal static TimeSpan GetTimeSpan(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, bool gettersSupportKatmaiDateTime) - { - if (gettersSupportKatmaiDateTime) - { - return GetTimeSpan(sink, (SmiTypedGetterSetter)getters, ordinal, metaData); - } - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - object obj = GetValue(sink, getters, ordinal, metaData, null); - if (null == obj) - { - throw ADP.InvalidCast(); - } - return (TimeSpan)obj; - } - - // dealing with v200 SMI - internal static TimeSpan GetTimeSpan(SmiEventSink_Default sink, SmiTypedGetterSetter getters, int ordinal, SmiMetaData metaData) - { - ThrowIfITypedGettersIsNull(sink, getters, ordinal); - if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.TimeSpan)) - { - return GetTimeSpan_Unchecked(sink, getters, ordinal); - } - return (TimeSpan)GetValue200(sink, getters, ordinal, metaData, null); - } - - // GetValue() for v200 SMI (new Katmai Date/Time types) - internal static object GetValue200( - SmiEventSink_Default sink, - SmiTypedGetterSetter getters, - int ordinal, - SmiMetaData metaData, - SmiContext context - ) - { - object result = null; - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = DBNull.Value; - } - else - { - switch (metaData.SqlDbType) - { - case SqlDbType.Variant: // Handle variants specifically for v200, since they could contain v200 types - metaData = getters.GetVariantType(sink, ordinal); - sink.ProcessMessagesAndThrow(); - Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant causes endless recursion!"); - result = GetValue200(sink, getters, ordinal, metaData, context); - break; - case SqlDbType.Date: - case SqlDbType.DateTime2: - result = GetDateTime_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Time: - result = GetTimeSpan_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.DateTimeOffset: - result = GetDateTimeOffset_Unchecked(sink, getters, ordinal); - break; - default: - result = GetValue(sink, getters, ordinal, metaData, context); - break; - } - } - - return result; - } - - // implements SqlClient 1.1-compatible GetValue() semantics for everything except output parameters - internal static object GetValue( - SmiEventSink_Default sink, - ITypedGettersV3 getters, - int ordinal, - SmiMetaData metaData, - SmiContext context - ) - { - object result = null; - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - result = DBNull.Value; - } - else - { - switch (metaData.SqlDbType) - { - case SqlDbType.BigInt: - result = GetInt64_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Binary: - result = GetByteArray_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Bit: - result = GetBoolean_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Char: - result = GetString_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.DateTime: - result = GetDateTime_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Decimal: - result = GetSqlDecimal_Unchecked(sink, getters, ordinal).Value; - break; - case SqlDbType.Float: - result = GetDouble_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Image: - result = GetByteArray_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Int: - result = GetInt32_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Money: - result = GetSqlMoney_Unchecked(sink, getters, ordinal).Value; - break; - case SqlDbType.NChar: - result = GetString_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.NText: - result = GetString_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.NVarChar: - result = GetString_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Real: - result = GetSingle_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.UniqueIdentifier: - result = GetGuid_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.SmallDateTime: - result = GetDateTime_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.SmallInt: - result = GetInt16_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.SmallMoney: - result = GetSqlMoney_Unchecked(sink, getters, ordinal).Value; - break; - case SqlDbType.Text: - result = GetString_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Timestamp: - result = GetByteArray_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.TinyInt: - result = GetByte_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.VarBinary: - result = GetByteArray_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.VarChar: - result = GetString_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Variant: - metaData = getters.GetVariantType(sink, ordinal); - sink.ProcessMessagesAndThrow(); - Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant causes endless recursion!"); - result = GetValue(sink, getters, ordinal, metaData, context); - break; - case SqlDbType.Xml: - result = GetSqlXml_Unchecked(sink, getters, ordinal, context).Value; - break; - case SqlDbType.Udt: - result = GetUdt_LengthChecked(sink, getters, ordinal, metaData); - break; - } - } - - return result; - } - - // dealing with v200 SMI - internal static object GetSqlValue200( - SmiEventSink_Default sink, - SmiTypedGetterSetter getters, - int ordinal, - SmiMetaData metaData, - SmiContext context - ) - { - object result = null; - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - if (SqlDbType.Udt == metaData.SqlDbType) - { - result = NullUdtInstance(metaData); - } - else - { - result = s_typeSpecificNullForSqlValue[(int)metaData.SqlDbType]; - } - } - else - { - switch (metaData.SqlDbType) - { - case SqlDbType.Variant: // Handle variants specifically for v200, since they could contain v200 types - metaData = getters.GetVariantType(sink, ordinal); - sink.ProcessMessagesAndThrow(); - Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant causes endless recursion!"); - result = GetSqlValue200(sink, getters, ordinal, metaData, context); - break; - case SqlDbType.Date: - case SqlDbType.DateTime2: - result = GetDateTime_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Time: - result = GetTimeSpan_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.DateTimeOffset: - result = GetDateTimeOffset_Unchecked(sink, getters, ordinal); - break; - default: - result = GetSqlValue(sink, getters, ordinal, metaData, context); - break; - } - } - - return result; - } - - // implements SqlClient 1.1-compatible GetSqlValue() semantics for everything except output parameters - internal static object GetSqlValue( - SmiEventSink_Default sink, - ITypedGettersV3 getters, - int ordinal, - SmiMetaData metaData, - SmiContext context - ) - { - object result = null; - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - if (SqlDbType.Udt == metaData.SqlDbType) - { - result = NullUdtInstance(metaData); - } - else - { - result = s_typeSpecificNullForSqlValue[(int)metaData.SqlDbType]; - } - } - else - { - switch (metaData.SqlDbType) - { - case SqlDbType.BigInt: - result = new SqlInt64(GetInt64_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.Binary: - result = GetSqlBinary_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Bit: - result = new SqlBoolean(GetBoolean_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.Char: - result = new SqlString(GetString_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.DateTime: - result = new SqlDateTime(GetDateTime_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.Decimal: - result = GetSqlDecimal_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Float: - result = new SqlDouble(GetDouble_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.Image: - result = GetSqlBinary_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Int: - result = new SqlInt32(GetInt32_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.Money: - result = GetSqlMoney_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.NChar: - result = new SqlString(GetString_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.NText: - result = new SqlString(GetString_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.NVarChar: - result = new SqlString(GetString_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.Real: - result = new SqlSingle(GetSingle_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.UniqueIdentifier: - result = new SqlGuid(GetGuid_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.SmallDateTime: - result = new SqlDateTime(GetDateTime_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.SmallInt: - result = new SqlInt16(GetInt16_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.SmallMoney: - result = GetSqlMoney_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Text: - result = new SqlString(GetString_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.Timestamp: - result = GetSqlBinary_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.TinyInt: - result = new SqlByte(GetByte_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.VarBinary: - result = GetSqlBinary_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.VarChar: - result = new SqlString(GetString_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.Variant: - metaData = getters.GetVariantType(sink, ordinal); - sink.ProcessMessagesAndThrow(); - Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant causes endless recursion!"); - result = GetSqlValue(sink, getters, ordinal, metaData, context); - break; - case SqlDbType.Xml: - result = GetSqlXml_Unchecked(sink, getters, ordinal, context); - break; - case SqlDbType.Udt: - result = GetUdt_LengthChecked(sink, getters, ordinal, metaData); - break; - } - } - - return result; - } - - // null return values for SqlClient 1.1-compatible GetSqlValue() - private static object[] s_typeSpecificNullForSqlValue = { - SqlInt64.Null, // SqlDbType.BigInt - SqlBinary.Null, // SqlDbType.Binary - SqlBoolean.Null, // SqlDbType.Bit - SqlString.Null, // SqlDbType.Char - SqlDateTime.Null, // SqlDbType.DateTime - SqlDecimal.Null, // SqlDbType.Decimal - SqlDouble.Null, // SqlDbType.Float - SqlBinary.Null, // SqlDbType.Image - SqlInt32.Null, // SqlDbType.Int - SqlMoney.Null, // SqlDbType.Money - SqlString.Null, // SqlDbType.NChar - SqlString.Null, // SqlDbType.NText - SqlString.Null, // SqlDbType.NVarChar - SqlSingle.Null, // SqlDbType.Real - SqlGuid.Null, // SqlDbType.UniqueIdentifier - SqlDateTime.Null, // SqlDbType.SmallDateTime - SqlInt16.Null, // SqlDbType.SmallInt - SqlMoney.Null, // SqlDbType.SmallMoney - SqlString.Null, // SqlDbType.Text - SqlBinary.Null, // SqlDbType.Timestamp - SqlByte.Null, // SqlDbType.TinyInt - SqlBinary.Null, // SqlDbType.VarBinary - SqlString.Null, // SqlDbType.VarChar - DBNull.Value, // SqlDbType.Variant - null, // 24 - SqlXml.Null, // SqlDbType.Xml - null, // 26 - null, // 27 - null, // 28 - null, // SqlDbType.Udt -- requires instantiating udt-specific type - null, // SqlDbType.Structured - DBNull.Value, // SqlDbType.Date - DBNull.Value, // SqlDbType.Time - DBNull.Value, // SqlDbType.DateTime2 - DBNull.Value, // SqlDbType.DateTimeOffset - }; - - internal static object NullUdtInstance(SmiMetaData metaData) - { - Type t = metaData.Type; - Debug.Assert(t != null, "Unexpected null of Udt type on NullUdtInstance!"); - return t.InvokeMember("Null", BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Static, null, null, new Object[] { }, CultureInfo.InvariantCulture); - } - - internal static SqlBuffer.StorageType SqlDbTypeToStorageType(SqlDbType dbType) - { - int index = unchecked((int)dbType); - Debug.Assert(index >= 0 && index < __dbTypeToStorageType.Length, string.Format(CultureInfo.InvariantCulture, "Unexpected dbType value: {0}", dbType)); - return __dbTypeToStorageType[index]; - } - - private static void GetNullOutputParameterSmi(SmiMetaData metaData, SqlBuffer targetBuffer, ref object result) - { - if (SqlDbType.Udt == metaData.SqlDbType) - { - result = NullUdtInstance(metaData); - } - else - { - SqlBuffer.StorageType stype = SqlDbTypeToStorageType(metaData.SqlDbType); - if (SqlBuffer.StorageType.Empty == stype) - { - result = DBNull.Value; - } - else if (SqlBuffer.StorageType.SqlBinary == stype) - { - // special case SqlBinary, 'cause tds parser never sets SqlBuffer to null, just to empty! - targetBuffer.SqlBinary = SqlBinary.Null; - } - else if (SqlBuffer.StorageType.SqlGuid == stype) - { - targetBuffer.SqlGuid = SqlGuid.Null; - } - else - { - targetBuffer.SetToNullOfType(stype); - } - } - } - - // UDTs and null variants come back via return value, all else is via targetBuffer. - // implements SqlClient 2.0-compatible output parameter semantics - internal static object GetOutputParameterV3Smi( - SmiEventSink_Default sink, // event sink for errors - ITypedGettersV3 getters, // getters interface to grab value from - int ordinal, // parameter within getters - SmiMetaData metaData, // Getter's type for this ordinal - SmiContext context, // used to obtain scratch streams - SqlBuffer targetBuffer // destination - ) - { - object result = null; // Workaround for UDT hack in non-Smi code paths. - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - GetNullOutputParameterSmi(metaData, targetBuffer, ref result); - } - else - { - switch (metaData.SqlDbType) - { - case SqlDbType.BigInt: - targetBuffer.Int64 = GetInt64_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Binary: - case SqlDbType.Image: - case SqlDbType.Timestamp: - case SqlDbType.VarBinary: - targetBuffer.SqlBinary = GetSqlBinary_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Bit: - targetBuffer.Boolean = GetBoolean_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.NChar: - case SqlDbType.NText: - case SqlDbType.NVarChar: - case SqlDbType.Char: - case SqlDbType.VarChar: - case SqlDbType.Text: - targetBuffer.SetToString(GetString_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.DateTime: - case SqlDbType.SmallDateTime: - { - SqlDateTime dt = new SqlDateTime(GetDateTime_Unchecked(sink, getters, ordinal)); - targetBuffer.SetToDateTime(dt.DayTicks, dt.TimeTicks); - break; - } - case SqlDbType.Decimal: - { - SqlDecimal dec = GetSqlDecimal_Unchecked(sink, getters, ordinal); - targetBuffer.SetToDecimal(dec.Precision, dec.Scale, dec.IsPositive, dec.Data); - break; - } - case SqlDbType.Float: - targetBuffer.Double = GetDouble_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Int: - targetBuffer.Int32 = GetInt32_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Money: - case SqlDbType.SmallMoney: - targetBuffer.SetToMoney(GetInt64_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.Real: - targetBuffer.Single = GetSingle_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.UniqueIdentifier: - targetBuffer.SqlGuid = new SqlGuid(GetGuid_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.SmallInt: - targetBuffer.Int16 = GetInt16_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.TinyInt: - targetBuffer.Byte = GetByte_Unchecked(sink, getters, ordinal); - break; - case SqlDbType.Variant: - // For variants, recur using the current value's sqldbtype - metaData = getters.GetVariantType(sink, ordinal); - sink.ProcessMessagesAndThrow(); - Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant not supposed to be possible!"); - GetOutputParameterV3Smi(sink, getters, ordinal, metaData, context, targetBuffer); - break; - case SqlDbType.Udt: - result = GetUdt_LengthChecked(sink, getters, ordinal, metaData); - break; - case SqlDbType.Xml: - targetBuffer.SqlXml = GetSqlXml_Unchecked(sink, getters, ordinal, null); - break; - default: - Debug.Assert(false, "Unexpected SqlDbType"); - break; - } - } - - return result; - } - - // UDTs and null variants come back via return value, all else is via targetBuffer. - // implements SqlClient 1.1-compatible output parameter semantics - internal static object GetOutputParameterV200Smi( - SmiEventSink_Default sink, // event sink for errors - SmiTypedGetterSetter getters, // getters interface to grab value from - int ordinal, // parameter within getters - SmiMetaData metaData, // Getter's type for this ordinal - SmiContext context, // used to obtain scratch streams - SqlBuffer targetBuffer // destination - ) - { - object result = null; // Workaround for UDT hack in non-Smi code paths. - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - GetNullOutputParameterSmi(metaData, targetBuffer, ref result); - } - else - { - switch (metaData.SqlDbType) - { - // new types go here - case SqlDbType.Variant: // Handle variants specifically for v200, since they could contain v200 types - // For variants, recur using the current value's sqldbtype - metaData = getters.GetVariantType(sink, ordinal); - sink.ProcessMessagesAndThrow(); - Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant not supposed to be possible!"); - GetOutputParameterV200Smi(sink, getters, ordinal, metaData, context, targetBuffer); - break; - case SqlDbType.Date: - targetBuffer.SetToDate(GetDateTime_Unchecked(sink, getters, ordinal)); - break; - case SqlDbType.DateTime2: - targetBuffer.SetToDateTime2(GetDateTime_Unchecked(sink, getters, ordinal), metaData.Scale); - break; - case SqlDbType.Time: - targetBuffer.SetToTime(GetTimeSpan_Unchecked(sink, getters, ordinal), metaData.Scale); - break; - case SqlDbType.DateTimeOffset: - targetBuffer.SetToDateTimeOffset(GetDateTimeOffset_Unchecked(sink, getters, ordinal), metaData.Scale); - break; - default: - result = GetOutputParameterV3Smi(sink, getters, ordinal, metaData, context, targetBuffer); - break; - } - } - - return result; - } - - private static SqlBuffer.StorageType[] __dbTypeToStorageType = new SqlBuffer.StorageType[] { - SqlBuffer.StorageType.Int64, // BigInt - SqlBuffer.StorageType.SqlBinary, // Binary - SqlBuffer.StorageType.Boolean, // Bit - SqlBuffer.StorageType.String, // Char - SqlBuffer.StorageType.DateTime, // DateTime - SqlBuffer.StorageType.Decimal, // Decimal - SqlBuffer.StorageType.Double, // Float - SqlBuffer.StorageType.SqlBinary, // Image - SqlBuffer.StorageType.Int32, // Int - SqlBuffer.StorageType.Money, // Money - SqlBuffer.StorageType.String, // NChar - SqlBuffer.StorageType.String, // NText - SqlBuffer.StorageType.String, // NVarChar - SqlBuffer.StorageType.Single, // Real - SqlBuffer.StorageType.SqlGuid, // UniqueIdentifier - SqlBuffer.StorageType.DateTime, // SmallDateTime - SqlBuffer.StorageType.Int16, // SmallInt - SqlBuffer.StorageType.Money, // SmallMoney - SqlBuffer.StorageType.String, // Text - SqlBuffer.StorageType.SqlBinary, // Timestamp - SqlBuffer.StorageType.Byte, // TinyInt - SqlBuffer.StorageType.SqlBinary, // VarBinary - SqlBuffer.StorageType.String, // VarChar - SqlBuffer.StorageType.Empty, // Variant - SqlBuffer.StorageType.Empty, // 24 - SqlBuffer.StorageType.SqlXml, // Xml - SqlBuffer.StorageType.Empty, // 26 - SqlBuffer.StorageType.Empty, // 27 - SqlBuffer.StorageType.Empty, // 28 - SqlBuffer.StorageType.Empty, // Udt - SqlBuffer.StorageType.Empty, // Structured - SqlBuffer.StorageType.Date, // Date - SqlBuffer.StorageType.Time, // Time - SqlBuffer.StorageType.DateTime2, // DateTime2 - SqlBuffer.StorageType.DateTimeOffset, // DateTimeOffset - }; - - // Strongly-typed setters are a bit simpler than their corresponding getters. - // 1) check to make sure the type is compatible (exception if not) - // 2) push the data - internal static void SetDBNull(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, bool value) - { - SetDBNull_Unchecked(sink, setters, ordinal); - } - - internal static void SetBoolean(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, bool value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Boolean); - - SetBoolean_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetByte(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, byte value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Byte); - - SetByte_Unchecked(sink, setters, ordinal, value); - } - - internal static long SetBytes(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, long fieldOffset, byte[] buffer, int bufferOffset, int length) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.ByteArray); - if (null == buffer) - { - throw ADP.ArgumentNull(nameof(buffer)); - } - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, fieldOffset, buffer.Length, bufferOffset, length); - Debug.Assert(length >= 0, "Buffer.Length was invalid!"); - if (0 == length) - { - // Front end semantics says to ignore fieldOffset and bufferOffset - // if not doing any actual work. - // Back end semantics says they must be valid, even for no work. - // Compensate by setting offsets to zero here (valid for any scenario) - fieldOffset = 0; - bufferOffset = 0; - } - return SetBytes_Unchecked(sink, setters, ordinal, fieldOffset, buffer, bufferOffset, length); - } - - internal static long SetBytesLength(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, long length) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.ByteArray); - - if (length < 0) - { - throw ADP.InvalidDataLength(length); - } - - if (metaData.MaxLength >= 0 && length > metaData.MaxLength) - { - length = metaData.MaxLength; - } - - setters.SetBytesLength(sink, ordinal, length); - sink.ProcessMessagesAndThrow(); - - return length; - } - - internal static long SetChars(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, long fieldOffset, char[] buffer, int bufferOffset, int length) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.CharArray); - if (null == buffer) - { - throw ADP.ArgumentNull(nameof(buffer)); - } - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, fieldOffset, buffer.Length, bufferOffset, length); - Debug.Assert(length >= 0, "Buffer.Length was invalid!"); - if (0 == length) - { - // Front end semantics says to ignore fieldOffset and bufferOffset - // if not doing any actual work. - // Back end semantics says they must be valid, even for no work. - // Compensate by setting offsets to zero here (valid for any scenario) - fieldOffset = 0; - bufferOffset = 0; - } - return SetChars_Unchecked(sink, setters, ordinal, fieldOffset, buffer, bufferOffset, length); - } - - internal static void SetDateTime(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTime value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.DateTime); - - SetDateTime_Checked(sink, setters, ordinal, metaData, value); - } - - internal static void SetDateTimeOffset(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTimeOffset value, bool settersSupportKatmaiDateTime) - { - if (!settersSupportKatmaiDateTime) - { - throw ADP.InvalidCast(); - } - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.DateTimeOffset); - SetDateTimeOffset_Unchecked(sink, (SmiTypedGetterSetter)setters, ordinal, value); - } - - internal static void SetDecimal(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, decimal value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Decimal); - - SetDecimal_PossiblyMoney(sink, setters, ordinal, metaData, value); - } - - internal static void SetDouble(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, double value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Double); - - SetDouble_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetGuid(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, Guid value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Guid); - - SetGuid_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetInt16(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, short value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Int16); - - SetInt16_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetInt32(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, int value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Int32); - - SetInt32_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetInt64(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, long value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Int64); - - SetInt64_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetSingle(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, float value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.Single); - - SetSingle_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetSqlBinary(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlBinary value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlBinary); - SetSqlBinary_LengthChecked(sink, setters, ordinal, metaData, value, 0); - } - - internal static void SetSqlBoolean(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlBoolean value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlBoolean); - - SetSqlBoolean_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetSqlByte(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlByte value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlByte); - - SetSqlByte_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetSqlBytes(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlBytes value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlBytes); - - SetSqlBytes_LengthChecked(sink, setters, ordinal, metaData, value, 0); - } - - internal static void SetSqlChars(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlChars value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlChars); - SetSqlChars_LengthChecked(sink, setters, ordinal, metaData, value, 0); - } - - internal static void SetSqlDateTime(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlDateTime value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlDateTime); - - SetSqlDateTime_Checked(sink, setters, ordinal, metaData, value); - } - - internal static void SetSqlDecimal(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlDecimal value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlDecimal); - - SetSqlDecimal_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetSqlDouble(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlDouble value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlDouble); - - SetSqlDouble_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetSqlGuid(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlGuid value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlGuid); - - SetSqlGuid_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetSqlInt16(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlInt16 value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlInt16); - - SetSqlInt16_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetSqlInt32(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlInt32 value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlInt32); - - SetSqlInt32_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetSqlInt64(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlInt64 value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlInt64); - - SetSqlInt64_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetSqlMoney(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlMoney value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlMoney); - - SetSqlMoney_Checked(sink, setters, ordinal, metaData, value); - } - - internal static void SetSqlSingle(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlSingle value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlSingle); - - SetSqlSingle_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetSqlString(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlString value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlString); - SetSqlString_LengthChecked(sink, setters, ordinal, metaData, value, 0); - } - - internal static void SetSqlXml(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlXml value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.SqlXml); - - SetSqlXml_Unchecked(sink, setters, ordinal, value); - } - - internal static void SetString(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, string value) - { - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.String); - - SetString_LengthChecked(sink, setters, ordinal, metaData, value, 0); - } - - internal static void SetTimeSpan(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, TimeSpan value, bool settersSupportKatmaiDateTime) - { - if (!settersSupportKatmaiDateTime) - { - throw ADP.InvalidCast(); - } - ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.TimeSpan); - SetTimeSpan_Checked(sink, (SmiTypedGetterSetter)setters, ordinal, metaData, value); - } - - // Implements SqlClient 2.0-compatible SetValue() semantics - // Assumes caller already validated type against the metadata, other than trimming lengths - internal static void SetCompatibleValue( - SmiEventSink_Default sink, - ITypedSettersV3 setters, - int ordinal, - SmiMetaData metaData, // metadata for target setter column - object value, - ExtendedClrTypeCode typeCode, - int offset - ) - { - // Ensure either an invalid type, or caller validated compatibility - // SqlDbType.Variant and have special handling - Debug.Assert(typeCode == ExtendedClrTypeCode.Invalid || - typeCode == ExtendedClrTypeCode.SByte || - typeCode == ExtendedClrTypeCode.UInt16 || - typeCode == ExtendedClrTypeCode.UInt32 || - typeCode == ExtendedClrTypeCode.UInt64 || - typeCode == ExtendedClrTypeCode.DBNull || - typeCode == ExtendedClrTypeCode.Empty || - CanAccessSetterDirectly(metaData, typeCode) || - value is DataFeed /* already validated */); - - switch (typeCode) - { - case ExtendedClrTypeCode.Invalid: - throw ADP.UnknownDataType(value.GetType()); - case ExtendedClrTypeCode.Boolean: - SetBoolean_Unchecked(sink, setters, ordinal, (bool)value); - break; - case ExtendedClrTypeCode.Byte: - SetByte_Unchecked(sink, setters, ordinal, (byte)value); - break; - case ExtendedClrTypeCode.Char: - { - char[] charsValue = new char[] { (char)value }; - // recur with array type - SetCompatibleValue(sink, setters, ordinal, metaData, charsValue, ExtendedClrTypeCode.CharArray, 0); - break; - } - case ExtendedClrTypeCode.DateTime: - SetDateTime_Checked(sink, setters, ordinal, metaData, (DateTime)value); - break; - case ExtendedClrTypeCode.DBNull: - SetDBNull_Unchecked(sink, setters, ordinal); - break; - case ExtendedClrTypeCode.Decimal: - SetDecimal_PossiblyMoney(sink, setters, ordinal, metaData, (decimal)value); - break; - case ExtendedClrTypeCode.Double: - SetDouble_Unchecked(sink, setters, ordinal, (double)value); - break; - case ExtendedClrTypeCode.Empty: - SetDBNull_Unchecked(sink, setters, ordinal); - break; - case ExtendedClrTypeCode.Int16: - SetInt16_Unchecked(sink, setters, ordinal, (short)value); - break; - case ExtendedClrTypeCode.Int32: - SetInt32_Unchecked(sink, setters, ordinal, (int)value); - break; - case ExtendedClrTypeCode.Int64: - SetInt64_Unchecked(sink, setters, ordinal, (long)value); - break; - case ExtendedClrTypeCode.SByte: - throw ADP.InvalidCast(); - case ExtendedClrTypeCode.Single: - SetSingle_Unchecked(sink, setters, ordinal, (float)value); - break; - case ExtendedClrTypeCode.String: - SetString_LengthChecked(sink, setters, ordinal, metaData, (string)value, offset); - break; - case ExtendedClrTypeCode.UInt16: - throw ADP.InvalidCast(); - case ExtendedClrTypeCode.UInt32: - throw ADP.InvalidCast(); - case ExtendedClrTypeCode.UInt64: - throw ADP.InvalidCast(); - case ExtendedClrTypeCode.Object: - SetUdt_LengthChecked(sink, setters, ordinal, metaData, value); - break; - case ExtendedClrTypeCode.ByteArray: - SetByteArray_LengthChecked(sink, setters, ordinal, metaData, (byte[])value, offset); - break; - case ExtendedClrTypeCode.CharArray: - SetCharArray_LengthChecked(sink, setters, ordinal, metaData, (char[])value, offset); - break; - case ExtendedClrTypeCode.Guid: - SetGuid_Unchecked(sink, setters, ordinal, (Guid)value); - break; - case ExtendedClrTypeCode.SqlBinary: - SetSqlBinary_LengthChecked(sink, setters, ordinal, metaData, (SqlBinary)value, offset); - break; - case ExtendedClrTypeCode.SqlBoolean: - SetSqlBoolean_Unchecked(sink, setters, ordinal, (SqlBoolean)value); - break; - case ExtendedClrTypeCode.SqlByte: - SetSqlByte_Unchecked(sink, setters, ordinal, (SqlByte)value); - break; - case ExtendedClrTypeCode.SqlDateTime: - SetSqlDateTime_Checked(sink, setters, ordinal, metaData, (SqlDateTime)value); - break; - case ExtendedClrTypeCode.SqlDouble: - SetSqlDouble_Unchecked(sink, setters, ordinal, (SqlDouble)value); - break; - case ExtendedClrTypeCode.SqlGuid: - SetSqlGuid_Unchecked(sink, setters, ordinal, (SqlGuid)value); - break; - case ExtendedClrTypeCode.SqlInt16: - SetSqlInt16_Unchecked(sink, setters, ordinal, (SqlInt16)value); - break; - case ExtendedClrTypeCode.SqlInt32: - SetSqlInt32_Unchecked(sink, setters, ordinal, (SqlInt32)value); - break; - case ExtendedClrTypeCode.SqlInt64: - SetSqlInt64_Unchecked(sink, setters, ordinal, (SqlInt64)value); - break; - case ExtendedClrTypeCode.SqlMoney: - SetSqlMoney_Checked(sink, setters, ordinal, metaData, (SqlMoney)value); - break; - case ExtendedClrTypeCode.SqlDecimal: - SetSqlDecimal_Unchecked(sink, setters, ordinal, (SqlDecimal)value); - break; - case ExtendedClrTypeCode.SqlSingle: - SetSqlSingle_Unchecked(sink, setters, ordinal, (SqlSingle)value); - break; - case ExtendedClrTypeCode.SqlString: - SetSqlString_LengthChecked(sink, setters, ordinal, metaData, (SqlString)value, offset); - break; - case ExtendedClrTypeCode.SqlChars: - SetSqlChars_LengthChecked(sink, setters, ordinal, metaData, (SqlChars)value, offset); - break; - case ExtendedClrTypeCode.SqlBytes: - SetSqlBytes_LengthChecked(sink, setters, ordinal, metaData, (SqlBytes)value, offset); - break; - case ExtendedClrTypeCode.SqlXml: - SetSqlXml_Unchecked(sink, setters, ordinal, (SqlXml)value); - break; - case ExtendedClrTypeCode.Stream: - SetStream_Unchecked(sink, setters, ordinal, metaData, (StreamDataFeed)value); - break; - case ExtendedClrTypeCode.TextReader: - SetTextReader_Unchecked(sink, setters, ordinal, metaData, (TextDataFeed)value); - break; - case ExtendedClrTypeCode.XmlReader: - SetXmlReader_Unchecked(sink, setters, ordinal, ((XmlDataFeed)value)._source); - break; - default: - Debug.Fail("Unvalidated extendedtypecode: " + typeCode); - break; - } - } - - // VSTFDevDiv#479681 - Data corruption when sending Katmai Date types to the server via TVP - // Ensures proper handling on DateTime2 sub type for Sql_Variants and TVPs. - internal static void SetCompatibleValueV200( - SmiEventSink_Default sink, - SmiTypedGetterSetter setters, - int ordinal, - SmiMetaData metaData, - object value, - ExtendedClrTypeCode typeCode, - int offset, - int length, - ParameterPeekAheadValue peekAhead, - SqlBuffer.StorageType storageType - ) - { - // Ensure caller validated compatibility for types handled directly in this method - Debug.Assert((ExtendedClrTypeCode.DataTable != typeCode && - ExtendedClrTypeCode.DbDataReader != typeCode && - ExtendedClrTypeCode.IEnumerableOfSqlDataRecord != typeCode) || - CanAccessSetterDirectly(metaData, typeCode), "Un-validated type '" + typeCode + "' for metaData: " + metaData.SqlDbType); - - if (typeCode == ExtendedClrTypeCode.DateTime) - { - if (storageType == SqlBuffer.StorageType.DateTime2) - SetDateTime2_Checked(sink, setters, ordinal, metaData, (DateTime)value); - else if (storageType == SqlBuffer.StorageType.Date) - SetDate_Checked(sink, setters, ordinal, metaData, (DateTime)value); - else - SetDateTime_Checked(sink, setters, ordinal, metaData, (DateTime)value); - } - else - { - SetCompatibleValueV200(sink, setters, ordinal, metaData, value, typeCode, offset, length, peekAhead); - } - } - - // Implements SqlClient 2.0-compatible SetValue() semantics + Orcas extensions - // Assumes caller already validated basic type against the metadata, other than trimming lengths and - // checking individual field values (TVPs) - internal static void SetCompatibleValueV200( - SmiEventSink_Default sink, - SmiTypedGetterSetter setters, - int ordinal, - SmiMetaData metaData, - object value, - ExtendedClrTypeCode typeCode, - int offset, - int length, - ParameterPeekAheadValue peekAhead - ) - { - // Ensure caller validated compatibility for types handled directly in this method - Debug.Assert((ExtendedClrTypeCode.DataTable != typeCode && - ExtendedClrTypeCode.DbDataReader != typeCode && - ExtendedClrTypeCode.IEnumerableOfSqlDataRecord != typeCode) || - CanAccessSetterDirectly(metaData, typeCode), "Un-validated type '" + typeCode + "' for metaData: " + metaData.SqlDbType); - - switch (typeCode) - { - case ExtendedClrTypeCode.DataTable: - SetDataTable_Unchecked(sink, setters, ordinal, metaData, (DataTable)value); - break; - case ExtendedClrTypeCode.DbDataReader: - SetDbDataReader_Unchecked(sink, setters, ordinal, metaData, (DbDataReader)value); - break; - case ExtendedClrTypeCode.IEnumerableOfSqlDataRecord: - SetIEnumerableOfSqlDataRecord_Unchecked(sink, setters, ordinal, metaData, (IEnumerable)value, peekAhead); - break; - case ExtendedClrTypeCode.TimeSpan: - SetTimeSpan_Checked(sink, setters, ordinal, metaData, (TimeSpan)value); - break; - case ExtendedClrTypeCode.DateTimeOffset: - SetDateTimeOffset_Unchecked(sink, setters, ordinal, (DateTimeOffset)value); - break; - default: - SetCompatibleValue(sink, setters, ordinal, metaData, value, typeCode, offset); - break; - } - } - - // Copy multiple fields from reader to ITypedSettersV3 - // Assumes caller enforces that reader and setter metadata are compatible - internal static void FillCompatibleITypedSettersFromReader(SmiEventSink_Default sink, ITypedSettersV3 setters, SmiMetaData[] metaData, SqlDataReader reader) - { - for (int i = 0; i < metaData.Length; i++) - { - if (reader.IsDBNull(i)) - { - ValueUtilsSmi.SetDBNull_Unchecked(sink, setters, i); - } - else - { - switch (metaData[i].SqlDbType) - { - case SqlDbType.BigInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int64)); - ValueUtilsSmi.SetInt64_Unchecked(sink, setters, i, reader.GetInt64(i)); - break; - case SqlDbType.Binary: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - ValueUtilsSmi.SetSqlBytes_LengthChecked(sink, setters, i, metaData[i], reader.GetSqlBytes(i), 0); - break; - case SqlDbType.Bit: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Boolean)); - SetBoolean_Unchecked(sink, setters, i, reader.GetBoolean(i)); - break; - case SqlDbType.Char: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); - SetSqlChars_LengthChecked(sink, setters, i, metaData[i], reader.GetSqlChars(i), 0); - break; - case SqlDbType.DateTime: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); - SetDateTime_Checked(sink, setters, i, metaData[i], reader.GetDateTime(i)); - break; - case SqlDbType.Decimal: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlDecimal)); - SetSqlDecimal_Unchecked(sink, setters, i, reader.GetSqlDecimal(i)); - break; - case SqlDbType.Float: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Double)); - SetDouble_Unchecked(sink, setters, i, reader.GetDouble(i)); - break; - case SqlDbType.Image: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetSqlBytes_LengthChecked(sink, setters, i, metaData[i], reader.GetSqlBytes(i), 0); - break; - case SqlDbType.Int: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int32)); - SetInt32_Unchecked(sink, setters, i, reader.GetInt32(i)); - break; - case SqlDbType.Money: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney)); - SetSqlMoney_Unchecked(sink, setters, i, metaData[i], reader.GetSqlMoney(i)); - break; - case SqlDbType.NChar: - case SqlDbType.NText: - case SqlDbType.NVarChar: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); - SetSqlChars_LengthChecked(sink, setters, i, metaData[i], reader.GetSqlChars(i), 0); - break; - case SqlDbType.Real: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Single)); - SetSingle_Unchecked(sink, setters, i, reader.GetFloat(i)); - break; - case SqlDbType.UniqueIdentifier: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Guid)); - SetGuid_Unchecked(sink, setters, i, reader.GetGuid(i)); - break; - case SqlDbType.SmallDateTime: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); - SetDateTime_Checked(sink, setters, i, metaData[i], reader.GetDateTime(i)); - break; - case SqlDbType.SmallInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int16)); - SetInt16_Unchecked(sink, setters, i, reader.GetInt16(i)); - break; - case SqlDbType.SmallMoney: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney)); - SetSqlMoney_Checked(sink, setters, i, metaData[i], reader.GetSqlMoney(i)); - break; - case SqlDbType.Text: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); - SetSqlChars_LengthChecked(sink, setters, i, metaData[i], reader.GetSqlChars(i), 0); - break; - case SqlDbType.Timestamp: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetSqlBytes_LengthChecked(sink, setters, i, metaData[i], reader.GetSqlBytes(i), 0); - break; - case SqlDbType.TinyInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Byte)); - SetByte_Unchecked(sink, setters, i, reader.GetByte(i)); - break; - case SqlDbType.VarBinary: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetSqlBytes_LengthChecked(sink, setters, i, metaData[i], reader.GetSqlBytes(i), 0); - break; - case SqlDbType.VarChar: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.String)); - SetSqlChars_LengthChecked(sink, setters, i, metaData[i], reader.GetSqlChars(i), 0); - break; - case SqlDbType.Xml: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlXml)); - SetSqlXml_Unchecked(sink, setters, i, reader.GetSqlXml(i)); - break; - case SqlDbType.Variant: - object o = reader.GetSqlValue(i); - ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCode(o); - SetCompatibleValue(sink, setters, i, metaData[i], o, typeCode, 0); - break; - - case SqlDbType.Udt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetSqlBytes_LengthChecked(sink, setters, i, metaData[i], reader.GetSqlBytes(i), 0); - break; - - default: - // In order for us to get here we would have to have an - // invalid instance of SqlDbType, or one would have to add - // new member to SqlDbType without adding a case in this - // switch, hence the assert. - Debug.Fail("unsupported DbType:" + metaData[i].SqlDbType.ToString()); - throw ADP.NotSupported(); - } - } - } - } - - // Copy multiple fields from reader to SmiTypedGetterSetter - // Supports V200 code path, without damaging backward compat for V100 code. - // Main differences are supporting DbDataReader, and for binary, character, decimal and Udt types. - // Assumes caller enforces that reader and setter metadata are compatible - internal static void FillCompatibleSettersFromReader(SmiEventSink_Default sink, SmiTypedGetterSetter setters, IList metaData, DbDataReader reader) - { - for (int i = 0; i < metaData.Count; i++) - { - if (reader.IsDBNull(i)) - { - ValueUtilsSmi.SetDBNull_Unchecked(sink, setters, i); - } - else - { - switch (metaData[i].SqlDbType) - { - case SqlDbType.BigInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int64)); - SetInt64_Unchecked(sink, setters, i, reader.GetInt64(i)); - break; - case SqlDbType.Binary: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.ByteArray)); - SetBytes_FromReader(sink, setters, i, metaData[i], reader, 0); - break; - case SqlDbType.Bit: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Boolean)); - SetBoolean_Unchecked(sink, setters, i, reader.GetBoolean(i)); - break; - case SqlDbType.Char: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.CharArray)); - SetCharsOrString_FromReader(sink, setters, i, metaData[i], reader, 0); - break; - case SqlDbType.DateTime: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); - SetDateTime_Checked(sink, setters, i, metaData[i], reader.GetDateTime(i)); - break; - case SqlDbType.Decimal: - { // block to scope sqlReader local to avoid conflicts - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlDecimal)); - // Support full fidelity for SqlDataReader - SqlDataReader sqlReader = reader as SqlDataReader; - if (null != sqlReader) - { - SetSqlDecimal_Unchecked(sink, setters, i, sqlReader.GetSqlDecimal(i)); - } - else - { - SetSqlDecimal_Unchecked(sink, setters, i, new SqlDecimal(reader.GetDecimal(i))); - } - } - break; - case SqlDbType.Float: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Double)); - SetDouble_Unchecked(sink, setters, i, reader.GetDouble(i)); - break; - case SqlDbType.Image: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.ByteArray)); - SetBytes_FromReader(sink, setters, i, metaData[i], reader, 0); - break; - case SqlDbType.Int: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int32)); - SetInt32_Unchecked(sink, setters, i, reader.GetInt32(i)); - break; - case SqlDbType.Money: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney)); - SetSqlMoney_Checked(sink, setters, i, metaData[i], new SqlMoney(reader.GetDecimal(i))); - break; - case SqlDbType.NChar: - case SqlDbType.NText: - case SqlDbType.NVarChar: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.CharArray)); - SetCharsOrString_FromReader(sink, setters, i, metaData[i], reader, 0); - break; - case SqlDbType.Real: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Single)); - SetSingle_Unchecked(sink, setters, i, reader.GetFloat(i)); - break; - case SqlDbType.UniqueIdentifier: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Guid)); - SetGuid_Unchecked(sink, setters, i, reader.GetGuid(i)); - break; - case SqlDbType.SmallDateTime: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); - SetDateTime_Checked(sink, setters, i, metaData[i], reader.GetDateTime(i)); - break; - case SqlDbType.SmallInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int16)); - SetInt16_Unchecked(sink, setters, i, reader.GetInt16(i)); - break; - case SqlDbType.SmallMoney: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney)); - SetSqlMoney_Checked(sink, setters, i, metaData[i], new SqlMoney(reader.GetDecimal(i))); - break; - case SqlDbType.Text: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.CharArray)); - SetCharsOrString_FromReader(sink, setters, i, metaData[i], reader, 0); - break; - case SqlDbType.Timestamp: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.ByteArray)); - SetBytes_FromReader(sink, setters, i, metaData[i], reader, 0); - break; - case SqlDbType.TinyInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Byte)); - SetByte_Unchecked(sink, setters, i, reader.GetByte(i)); - break; - case SqlDbType.VarBinary: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.ByteArray)); - SetBytes_FromReader(sink, setters, i, metaData[i], reader, 0); - break; - case SqlDbType.VarChar: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.String)); - SetCharsOrString_FromReader(sink, setters, i, metaData[i], reader, 0); - break; - case SqlDbType.Xml: - { - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlXml)); - SqlDataReader sqlReader = reader as SqlDataReader; - if (null != sqlReader) - { - SetSqlXml_Unchecked(sink, setters, i, sqlReader.GetSqlXml(i)); - } - else - { - SetBytes_FromReader(sink, setters, i, metaData[i], reader, 0); - } - } - break; - case SqlDbType.Variant: - { // block to scope sqlReader local and avoid conflicts - // Support better options for SqlDataReader - SqlDataReader sqlReader = reader as SqlDataReader; - SqlBuffer.StorageType storageType = SqlBuffer.StorageType.Empty; - object o; - if (null != sqlReader) - { - o = sqlReader.GetSqlValue(i); - storageType = sqlReader.GetVariantInternalStorageType(i); - } - else - { - o = reader.GetValue(i); - } - ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType(metaData[i].SqlDbType, metaData[i].IsMultiValued, o, null, - // TODO: this version works for shipping Orcas, since only Katmai (TVP) codepath calls this method at this time. - // Need a better story for smi versioning of ValueUtilsSmi post-Orcas - SmiContextFactory.KatmaiVersion - ); - if ((storageType == SqlBuffer.StorageType.DateTime2) || (storageType == SqlBuffer.StorageType.Date)) - SetCompatibleValueV200(sink, setters, i, metaData[i], o, typeCode, 0, 0, null, storageType); - else - SetCompatibleValueV200(sink, setters, i, metaData[i], o, typeCode, 0, 0, null); - } - break; - - case SqlDbType.Udt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.ByteArray)); - // Skip serialization for Udt types. - SetBytes_FromReader(sink, setters, i, metaData[i], reader, 0); - break; - - // SqlDbType.Structured should have been caught before this point for TVPs. SUDTs will still need to implement. - - case SqlDbType.Date: - case SqlDbType.DateTime2: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); - SetDateTime_Checked(sink, setters, i, metaData[i], reader.GetDateTime(i)); - break; - case SqlDbType.Time: - { // block to scope sqlReader local and avoid conflicts - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.TimeSpan)); - SqlDataReader sqlReader = reader as SqlDataReader; - TimeSpan ts; - if (null != sqlReader) - { - ts = sqlReader.GetTimeSpan(i); - } - else - { - ts = (TimeSpan)reader.GetValue(i); - } - SetTimeSpan_Checked(sink, setters, i, metaData[i], ts); - } - break; - case SqlDbType.DateTimeOffset: - { // block to scope sqlReader local and avoid conflicts - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTimeOffset)); - SqlDataReader sqlReader = reader as SqlDataReader; - DateTimeOffset dto; - if (null != sqlReader) - { - dto = sqlReader.GetDateTimeOffset(i); - } - else - { - dto = (DateTimeOffset)reader.GetValue(i); - } - SetDateTimeOffset_Unchecked(sink, setters, i, dto); - } - break; - - default: - // In order for us to get here we would have to have an - // invalid instance of SqlDbType, or one would have to add - // new member to SqlDbType without adding a case in this - // switch, hence the assert. - Debug.Fail("unsupported DbType:" + metaData[i].SqlDbType.ToString()); - throw ADP.NotSupported(); - } - } - } - } - - internal static void FillCompatibleITypedSettersFromRecord(SmiEventSink_Default sink, ITypedSettersV3 setters, SmiMetaData[] metaData, SqlDataRecord record) - { - FillCompatibleITypedSettersFromRecord(sink, setters, metaData, record, null); - } - - internal static void FillCompatibleITypedSettersFromRecord(SmiEventSink_Default sink, ITypedSettersV3 setters, SmiMetaData[] metaData, SqlDataRecord record, SmiDefaultFieldsProperty useDefaultValues) - { - for (int i = 0; i < metaData.Length; ++i) - { - if (null != useDefaultValues && useDefaultValues[i]) - { - continue; - } - if (record.IsDBNull(i)) - { - ValueUtilsSmi.SetDBNull_Unchecked(sink, setters, i); - } - else - { - switch (metaData[i].SqlDbType) - { - case SqlDbType.BigInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int64)); - SetInt64_Unchecked(sink, setters, i, record.GetInt64(i)); - break; - case SqlDbType.Binary: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.Bit: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Boolean)); - SetBoolean_Unchecked(sink, setters, i, record.GetBoolean(i)); - break; - case SqlDbType.Char: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); - SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.DateTime: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); - SetDateTime_Checked(sink, setters, i, metaData[i], record.GetDateTime(i)); - break; - case SqlDbType.Decimal: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlDecimal)); - SetSqlDecimal_Unchecked(sink, setters, i, record.GetSqlDecimal(i)); - break; - case SqlDbType.Float: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Double)); - SetDouble_Unchecked(sink, setters, i, record.GetDouble(i)); - break; - case SqlDbType.Image: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.Int: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int32)); - SetInt32_Unchecked(sink, setters, i, record.GetInt32(i)); - break; - case SqlDbType.Money: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney)); - SetSqlMoney_Unchecked(sink, setters, i, metaData[i], record.GetSqlMoney(i)); - break; - case SqlDbType.NChar: - case SqlDbType.NText: - case SqlDbType.NVarChar: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); - SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.Real: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Single)); - SetSingle_Unchecked(sink, setters, i, record.GetFloat(i)); - break; - case SqlDbType.UniqueIdentifier: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Guid)); - SetGuid_Unchecked(sink, setters, i, record.GetGuid(i)); - break; - case SqlDbType.SmallDateTime: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); - SetDateTime_Checked(sink, setters, i, metaData[i], record.GetDateTime(i)); - break; - case SqlDbType.SmallInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int16)); - SetInt16_Unchecked(sink, setters, i, record.GetInt16(i)); - break; - case SqlDbType.SmallMoney: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney)); - SetSqlMoney_Checked(sink, setters, i, metaData[i], record.GetSqlMoney(i)); - break; - case SqlDbType.Text: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); - SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.Timestamp: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.TinyInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Byte)); - SetByte_Unchecked(sink, setters, i, record.GetByte(i)); - break; - case SqlDbType.VarBinary: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.VarChar: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.String)); - SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.Xml: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlXml)); - SetSqlXml_Unchecked(sink, setters, i, record.GetSqlXml(i)); // perf improvement? - break; - case SqlDbType.Variant: - object o = record.GetSqlValue(i); - ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCode(o); - SetCompatibleValue(sink, setters, i, metaData[i], o, typeCode, 0); - break; - case SqlDbType.Udt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - default: - Debug.Assert(false, "unsupported DbType:" + metaData[i].SqlDbType.ToString()); - throw ADP.NotSupported(); - } - } - } - } - - internal static void FillCompatibleSettersFromRecord(SmiEventSink_Default sink, SmiTypedGetterSetter setters, SmiMetaData[] metaData, SqlDataRecord record, SmiDefaultFieldsProperty useDefaultValues) - { - for (int i = 0; i < metaData.Length; ++i) - { - if (null != useDefaultValues && useDefaultValues[i]) - { - continue; - } - if (record.IsDBNull(i)) - { - ValueUtilsSmi.SetDBNull_Unchecked(sink, setters, i); - } - else - { - switch (metaData[i].SqlDbType) - { - case SqlDbType.BigInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int64)); - SetInt64_Unchecked(sink, setters, i, record.GetInt64(i)); - break; - case SqlDbType.Binary: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.Bit: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Boolean)); - SetBoolean_Unchecked(sink, setters, i, record.GetBoolean(i)); - break; - case SqlDbType.Char: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); - SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.DateTime: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); - SetDateTime_Checked(sink, setters, i, metaData[i], record.GetDateTime(i)); - break; - case SqlDbType.Decimal: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlDecimal)); - SetSqlDecimal_Unchecked(sink, setters, i, record.GetSqlDecimal(i)); - break; - case SqlDbType.Float: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Double)); - SetDouble_Unchecked(sink, setters, i, record.GetDouble(i)); - break; - case SqlDbType.Image: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.Int: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int32)); - SetInt32_Unchecked(sink, setters, i, record.GetInt32(i)); - break; - case SqlDbType.Money: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney)); - SetSqlMoney_Unchecked(sink, setters, i, metaData[i], record.GetSqlMoney(i)); - break; - case SqlDbType.NChar: - case SqlDbType.NText: - case SqlDbType.NVarChar: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); - SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.Real: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Single)); - SetSingle_Unchecked(sink, setters, i, record.GetFloat(i)); - break; - case SqlDbType.UniqueIdentifier: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Guid)); - SetGuid_Unchecked(sink, setters, i, record.GetGuid(i)); - break; - case SqlDbType.SmallDateTime: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); - SetDateTime_Checked(sink, setters, i, metaData[i], record.GetDateTime(i)); - break; - case SqlDbType.SmallInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int16)); - SetInt16_Unchecked(sink, setters, i, record.GetInt16(i)); - break; - case SqlDbType.SmallMoney: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney)); - SetSqlMoney_Checked(sink, setters, i, metaData[i], record.GetSqlMoney(i)); - break; - case SqlDbType.Text: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); - SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.Timestamp: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.TinyInt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Byte)); - SetByte_Unchecked(sink, setters, i, record.GetByte(i)); - break; - case SqlDbType.VarBinary: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.VarChar: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.String)); - SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.Xml: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlXml)); - SetSqlXml_Unchecked(sink, setters, i, record.GetSqlXml(i)); // perf improvement? - break; - case SqlDbType.Variant: - object o = record.GetSqlValue(i); - ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCode(o); - SetCompatibleValueV200(sink, setters, i, metaData[i], o, typeCode, 0, -1 /* no length restriction */, null /* no peekahead */); - break; - case SqlDbType.Udt: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); - SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); - break; - case SqlDbType.Date: - case SqlDbType.DateTime2: - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); - SetDateTime_Checked(sink, setters, i, metaData[i], record.GetDateTime(i)); - break; - case SqlDbType.Time: - { // block to scope sqlReader local and avoid conflicts - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.TimeSpan)); - SqlDataRecord sqlRecord = record as SqlDataRecord; - TimeSpan ts; - if (null != sqlRecord) - { - ts = sqlRecord.GetTimeSpan(i); - } - else - { - ts = (TimeSpan)record.GetValue(i); - } - SetTimeSpan_Checked(sink, setters, i, metaData[i], ts); - } - break; - case SqlDbType.DateTimeOffset: - { // block to scope sqlReader local and avoid conflicts - Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTimeOffset)); - SqlDataRecord sqlRecord = record as SqlDataRecord; - DateTimeOffset dto; - if (null != sqlRecord) - { - dto = sqlRecord.GetDateTimeOffset(i); - } - else - { - dto = (DateTimeOffset)record.GetValue(i); - } - SetDateTimeOffset_Unchecked(sink, setters, i, dto); - } - break; - - default: - Debug.Fail("unsupported DbType:" + metaData[i].SqlDbType.ToString()); - throw ADP.NotSupported(); - } - } - } - } - - // spool a Stream into a scratch stream from the Smi interface and return it as a Stream - internal static Stream CopyIntoNewSmiScratchStream(Stream source, SmiEventSink_Default sink, SmiContext context) - { - Stream dest; - if (null == context) - { - dest = new MemoryStream(); - } - else - { - dest = new SqlClientWrapperSmiStream(sink, context.GetScratchStream(sink)); - } - - int chunkSize; - if (source.CanSeek && __maxByteChunkSize > source.Length) - { - chunkSize = unchecked((int)source.Length); // unchecked cast is safe due to check on line above - } - else - { - chunkSize = __maxByteChunkSize; - } - - byte[] copyBuffer = new byte[chunkSize]; - int bytesRead; - while (0 != (bytesRead = source.Read(copyBuffer, 0, chunkSize))) - { - dest.Write(copyBuffer, 0, bytesRead); - } - dest.Flush(); - - // SQLBU 494334 - // Need to re-wind scratch stream to beginning before returning - dest.Seek(0, SeekOrigin.Begin); - - return dest; - } - - // spool a Stream into a scratch stream from the Smi interface and return it as a SqlStreamChars - internal static SqlStreamChars CopyIntoNewSmiScratchStreamChars(Stream source, SmiEventSink_Default sink, SmiContext context) - { - SqlClientWrapperSmiStreamChars dest = new SqlClientWrapperSmiStreamChars(sink, context.GetScratchStream(sink)); - - int chunkSize; - if (source.CanSeek && __maxByteChunkSize > source.Length) - { - chunkSize = unchecked((int)source.Length); // unchecked cast is safe due to check on line above - } - else - { - chunkSize = __maxByteChunkSize; - } - - byte[] copyBuffer = new byte[chunkSize]; - int bytesRead; - while (0 != (bytesRead = source.Read(copyBuffer, 0, chunkSize))) - { - dest.Write(copyBuffer, 0, bytesRead); - } - dest.Flush(); - - // SQLBU 494334 - // Need to re-wind scratch stream to beginning before returning - dest.Seek(0, SeekOrigin.Begin); - - return dest; - } - - // - // Common utility code to get lengths correct for trimming - // - private static object GetUdt_LengthChecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - object result; - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - Type t = metaData.Type; - Debug.Assert(t != null, "Unexpected null of udtType on GetUdt_LengthChecked!"); - result = t.InvokeMember("Null", BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Static, null, null, Array.Empty(), CultureInfo.InvariantCulture); - Debug.Assert(result != null); - } - else - { - // Note: do not need to copy getter stream, since it will not be used beyond - // deserialization (valid lifetime of getters is limited). - Stream s = new SmiGettersStream(sink, getters, ordinal, metaData); - result = SerializationHelperSql9.Deserialize(s, metaData.Type); - } - return result; - } - - private static decimal GetDecimal_PossiblyMoney(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) - { - if (SqlDbType.Decimal == metaData.SqlDbType) - { - return GetSqlDecimal_Unchecked(sink, getters, ordinal).Value; - } - else - { - Debug.Assert(SqlDbType.Money == metaData.SqlDbType || - SqlDbType.SmallMoney == metaData.SqlDbType, - "Unexpected sqldbtype=" + metaData.SqlDbType); - return GetSqlMoney_Unchecked(sink, getters, ordinal).Value; - } - } - - private static void SetDecimal_PossiblyMoney(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, decimal value) - { - if (SqlDbType.Decimal == metaData.SqlDbType || SqlDbType.Variant == metaData.SqlDbType) - { - SetDecimal_Unchecked(sink, setters, ordinal, value); - } - else - { - Debug.Assert(SqlDbType.Money == metaData.SqlDbType || - SqlDbType.SmallMoney == metaData.SqlDbType, - "Unexpected sqldbtype=" + metaData.SqlDbType); - SetSqlMoney_Checked(sink, setters, ordinal, metaData, new SqlMoney(value)); - } - } - - // Hard coding smalldatetime limits... - private static readonly DateTime s_dtSmallMax = new DateTime(2079, 06, 06, 23, 59, 29, 998); - private static readonly DateTime s_dtSmallMin = new DateTime(1899, 12, 31, 23, 59, 29, 999); - private static void VerifyDateTimeRange(SqlDbType dbType, DateTime value) - { - if (SqlDbType.SmallDateTime == dbType && (s_dtSmallMax < value || s_dtSmallMin > value)) - { - throw ADP.InvalidMetaDataValue(); - } - } - - private static readonly TimeSpan s_timeMin = TimeSpan.Zero; - private static readonly TimeSpan s_timeMax = new TimeSpan(TimeSpan.TicksPerDay - 1); - private static void VerifyTimeRange(SqlDbType dbType, TimeSpan value) - { - if (SqlDbType.Time == dbType && (s_timeMin > value || value > s_timeMax)) - { - throw ADP.InvalidMetaDataValue(); - } - } - - private static void SetDateTime_Checked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTime value) - { - VerifyDateTimeRange(metaData.SqlDbType, value); - SetDateTime_Unchecked(sink, setters, ordinal, ((SqlDbType.Date == metaData.SqlDbType) ? value.Date : value)); - } - - private static void SetTimeSpan_Checked(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, SmiMetaData metaData, TimeSpan value) - { - VerifyTimeRange(metaData.SqlDbType, value); - SetTimeSpan_Unchecked(sink, setters, ordinal, value); - } - - private static void SetSqlDateTime_Checked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlDateTime value) - { - if (!value.IsNull) - { - VerifyDateTimeRange(metaData.SqlDbType, value.Value); - } - SetSqlDateTime_Unchecked(sink, setters, ordinal, value); - } - - private static void SetDateTime2_Checked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTime value) - { - VerifyDateTimeRange(metaData.SqlDbType, value); - SetDateTime2_Unchecked(sink, setters, ordinal, metaData, value); - } - - private static void SetDate_Checked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTime value) - { - VerifyDateTimeRange(metaData.SqlDbType, value); - SetDate_Unchecked(sink, setters, ordinal, metaData, value); - } - - private static void SetSqlMoney_Checked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlMoney value) - { - if (!value.IsNull && SqlDbType.SmallMoney == metaData.SqlDbType) - { - decimal decimalValue = value.Value; - if (TdsEnums.SQL_SMALL_MONEY_MIN > decimalValue || TdsEnums.SQL_SMALL_MONEY_MAX < decimalValue) - { - throw SQL.MoneyOverflow(decimalValue.ToString(CultureInfo.InvariantCulture)); - } - } - SetSqlMoney_Unchecked(sink, setters, ordinal, metaData, value); - } - - private static void SetByteArray_LengthChecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, byte[] buffer, int offset) - { - int length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, buffer.Length, offset, buffer.Length - offset); - Debug.Assert(length >= 0, "buffer.Length was invalid!"); - SetByteArray_Unchecked(sink, setters, ordinal, buffer, offset, length); - } - - private static void SetCharArray_LengthChecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, char[] buffer, int offset) - { - int length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, buffer.Length, offset, buffer.Length - offset); - Debug.Assert(length >= 0, "buffer.Length was invalid!"); - SetCharArray_Unchecked(sink, setters, ordinal, buffer, offset, length); - } - - private static void SetSqlBinary_LengthChecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlBinary value, int offset) - { - int length = 0; - if (!value.IsNull) - { - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, value.Length, offset, value.Length - offset); - Debug.Assert(length >= 0, "value.Length was invalid!"); - } - SetSqlBinary_Unchecked(sink, setters, ordinal, value, offset, length); - } - - private static void SetBytes_FromRecord(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlDataRecord record, int offset) - { - int length = 0; - - // Deal with large values by sending bufferLength of NoLengthLimit (== assume - // CheckXetParameters will ignore requested-length checks in this case - long bufferLength = record.GetBytes(ordinal, 0, null, 0, 0); - if (bufferLength > int.MaxValue) - { - bufferLength = NoLengthLimit; - } - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, checked((int)bufferLength), offset, checked((int)bufferLength)); - - int chunkSize; - if (length > __maxByteChunkSize || length < 0) - { - chunkSize = __maxByteChunkSize; - } - else - { - chunkSize = checked((int)length); - } - - byte[] buffer = new byte[chunkSize]; - long bytesRead; - long bytesWritten = 1; // prime value to get into write loop - long currentOffset = offset; - long lengthWritten = 0; - - while ((length < 0 || lengthWritten < length) && - 0 != (bytesRead = record.GetBytes(ordinal, currentOffset, buffer, 0, chunkSize)) && - 0 != bytesWritten) - { - bytesWritten = setters.SetBytes(sink, ordinal, currentOffset, buffer, 0, checked((int)bytesRead)); - sink.ProcessMessagesAndThrow(); - checked - { - currentOffset += bytesWritten; - } - checked - { - lengthWritten += bytesWritten; - } - } - - // Make sure to trim any left-over data - setters.SetBytesLength(sink, ordinal, currentOffset); - sink.ProcessMessagesAndThrow(); - } - - private static void SetBytes_FromReader(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, SmiMetaData metaData, DbDataReader reader, int offset) - { - int length = 0; - - // Deal with large values by sending bufferLength of NoLengthLimit (== assume - // CheckXetParameters will ignore requested-length checks in this case) - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, NoLengthLimit /* buffer length */, offset, NoLengthLimit /* requested length */ ); - - // Use fixed chunk size for all cases to avoid inquiring from reader. - int chunkSize = __maxByteChunkSize; - - byte[] buffer = new byte[chunkSize]; - long bytesRead; - long bytesWritten = 1; // prime value to get into write loop - long currentOffset = offset; - long lengthWritten = 0; - - while ((length < 0 || lengthWritten < length) && - 0 != (bytesRead = reader.GetBytes(ordinal, currentOffset, buffer, 0, chunkSize)) && - 0 != bytesWritten) - { - bytesWritten = setters.SetBytes(sink, ordinal, currentOffset, buffer, 0, checked((int)bytesRead)); - sink.ProcessMessagesAndThrow(); - checked - { - currentOffset += bytesWritten; - } - checked - { - lengthWritten += bytesWritten; - } - } - - // Make sure to trim any left-over data (remember to trim at end of offset, not just the amount written - setters.SetBytesLength(sink, ordinal, currentOffset); - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlBytes_LengthChecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlBytes value, int offset) - { - int length = 0; - if (!value.IsNull) - { - // Deal with large values by sending bufferLength of NoLengthLimit (== assume - // CheckXetParameters will ignore requested-length checks in this case - long bufferLength = value.Length; - if (bufferLength > int.MaxValue) - { - bufferLength = NoLengthLimit; - } - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, checked((int)bufferLength), offset, checked((int)bufferLength)); - } - SetSqlBytes_Unchecked(sink, setters, ordinal, value, 0, length); - } - - private static void SetChars_FromRecord(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlDataRecord record, int offset) - { - int length = 0; - - // Deal with large values by sending bufferLength of NoLengthLimit - // CheckXetParameters will ignore length checks in this case - long bufferLength = record.GetChars(ordinal, 0, null, 0, 0); - if (bufferLength > int.MaxValue) - { - bufferLength = NoLengthLimit; - } - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, checked((int)bufferLength), offset, checked((int)bufferLength - offset)); - - int chunkSize; - if (length > __maxCharChunkSize || length < 0) - { - if (MetaDataUtilsSmi.IsAnsiType(metaData.SqlDbType)) - { - chunkSize = __maxByteChunkSize; - } - else - { - chunkSize = __maxCharChunkSize; - } - } - else - { - chunkSize = checked((int)length); - } - - char[] buffer = new char[chunkSize]; - long charsRead; - long charsWritten = 1; // prime value to get into write loop - long currentOffset = offset; - long lengthWritten = 0; - - while ((length < 0 || lengthWritten < length) && - 0 != (charsRead = record.GetChars(ordinal, currentOffset, buffer, 0, chunkSize)) && - 0 != charsWritten) - { - charsWritten = setters.SetChars(sink, ordinal, currentOffset, buffer, 0, checked((int)charsRead)); - sink.ProcessMessagesAndThrow(); - checked - { - currentOffset += charsWritten; - } - checked - { - lengthWritten += charsWritten; - } - } - - // Make sure to trim any left-over data - setters.SetCharsLength(sink, ordinal, currentOffset); - sink.ProcessMessagesAndThrow(); - } - - // Transfer a character value from a reader when we're not sure which GetXXX method the reader will support. - // Prefers to chunk data via GetChars, but falls back to GetString if that fails. - // Mainly put in place because DataTableReader doesn't support GetChars on string columns, but others could fail too... - private static void SetCharsOrString_FromReader(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, SmiMetaData metaData, DbDataReader reader, int offset) - { - bool success = false; - try - { - SetChars_FromReader(sink, setters, ordinal, metaData, reader, offset); - success = true; - } - catch (Exception e) - { - if (!ADP.IsCatchableExceptionType(e)) - { - throw; - } - } - - if (!success) - { - SetString_FromReader(sink, setters, ordinal, metaData, reader, offset); - } - } - - // Use chunking via SetChars to transfer a value from a reader to a gettersetter - private static void SetChars_FromReader(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, SmiMetaData metaData, DbDataReader reader, int offset) - { - int length = 0; - - // Deal with large values by sending bufferLength of NoLengthLimit (== assume - // CheckXetParameters will ignore requested-length checks in this case) - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, NoLengthLimit /* buffer length */, offset, NoLengthLimit /* requested length */ ); - - // Use fixed chunk size for all cases to avoid inquiring from reader. - int chunkSize; - if (MetaDataUtilsSmi.IsAnsiType(metaData.SqlDbType)) - { - chunkSize = __maxByteChunkSize; - } - else - { - chunkSize = __maxCharChunkSize; - } - - char[] buffer = new char[chunkSize]; - long charsRead; - long charsWritten = 1; // prime value to get into write loop - long currentOffset = offset; - long lengthWritten = 0; - - while ((length < 0 || lengthWritten < length) && - 0 != (charsRead = reader.GetChars(ordinal, currentOffset, buffer, 0, chunkSize)) && - 0 != charsWritten) - { - charsWritten = setters.SetChars(sink, ordinal, currentOffset, buffer, 0, checked((int)charsRead)); - sink.ProcessMessagesAndThrow(); - checked - { - currentOffset += charsWritten; - } - checked - { - lengthWritten += charsWritten; - } - } - - // Make sure to trim any left-over data (remember to trim at end of offset, not just the amount written - setters.SetCharsLength(sink, ordinal, currentOffset); - sink.ProcessMessagesAndThrow(); - } - - private static void SetString_FromReader(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, SmiMetaData metaData, DbDataReader reader, int offset) - { - string value = reader.GetString(ordinal); - int length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, value.Length, 0, NoLengthLimit /* buffer */, offset, NoLengthLimit /* request */); - - setters.SetString(sink, ordinal, value, offset, length); - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlChars_LengthChecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlChars value, int offset) - { - int length = 0; - if (!value.IsNull) - { - // Deal with large values by sending bufferLength of NoLengthLimit - // CheckXetParameters will ignore length checks in this case - long bufferLength = value.Length; - if (bufferLength > int.MaxValue) - { - bufferLength = NoLengthLimit; - } - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, checked((int)bufferLength), offset, checked((int)bufferLength - offset)); - } - SetSqlChars_Unchecked(sink, setters, ordinal, value, 0, length); - } - - private static void SetSqlString_LengthChecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlString value, int offset) - { - if (value.IsNull) - { - SetDBNull_Unchecked(sink, setters, ordinal); - } - else - { - string stringValue = value.Value; - int length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, stringValue.Length, offset, stringValue.Length - offset); - Debug.Assert(length >= 0, "value.Length was invalid!"); - SetSqlString_Unchecked(sink, setters, ordinal, metaData, value, offset, length); - } - } - - private static void SetString_LengthChecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, string value, int offset) - { - int length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, value.Length, offset, checked(value.Length - offset)); - Debug.Assert(length >= 0, "value.Length was invalid!"); - SetString_Unchecked(sink, setters, ordinal, value, offset, length); - } - - private static void SetUdt_LengthChecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, object value) - { - if (ADP.IsNull(value)) - { - setters.SetDBNull(sink, ordinal); - sink.ProcessMessagesAndThrow(); - } - else - { - Stream target = new SmiSettersStream(sink, setters, ordinal, metaData); - SerializationHelperSql9.Serialize(target, value); - } - } - - // - // Semantics support routines - // - - private static void ThrowIfInvalidSetterAccess(SmiMetaData metaData, ExtendedClrTypeCode setterTypeCode) - { - if (!CanAccessSetterDirectly(metaData, setterTypeCode)) - { - throw ADP.InvalidCast(); - } - } - - private static void ThrowIfITypedGettersIsNull(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - if (IsDBNull_Unchecked(sink, getters, ordinal)) - { - throw SQL.SqlNullValue(); - } - } - - private static bool CanAccessGetterDirectly(SmiMetaData metaData, ExtendedClrTypeCode setterTypeCode) - { - // Make sure no-one adds new ExtendedType, nor SqlDbType without updating this file! - Debug.Assert(ExtendedClrTypeCode.First == 0 && (int)ExtendedClrTypeCode.Last == s_canAccessGetterDirectly.GetLength(0) - 1, "ExtendedClrTypeCodes does not match with __canAccessGetterDirectly"); - Debug.Assert(SqlDbType.BigInt == 0 && (int)SqlDbType.DateTimeOffset == s_canAccessGetterDirectly.GetLength(1) - 1, "SqlDbType does not match with __canAccessGetterDirectly"); - Debug.Assert(ExtendedClrTypeCode.First <= setterTypeCode && ExtendedClrTypeCode.Last >= setterTypeCode); - Debug.Assert(SqlDbType.BigInt <= metaData.SqlDbType && SqlDbType.DateTimeOffset >= metaData.SqlDbType); - - bool returnValue = s_canAccessGetterDirectly[(int)setterTypeCode, (int)metaData.SqlDbType]; - - // Additional restrictions to distinguish TVPs and Structured UDTs - if (returnValue && - (ExtendedClrTypeCode.DataTable == setterTypeCode || - ExtendedClrTypeCode.DbDataReader == setterTypeCode || - ExtendedClrTypeCode.IEnumerableOfSqlDataRecord == setterTypeCode)) - { - returnValue = metaData.IsMultiValued; - } - - return returnValue; - } - - private static bool CanAccessSetterDirectly(SmiMetaData metaData, ExtendedClrTypeCode setterTypeCode) - { - // Make sure no-one adds new ExtendedType, nor SqlDbType without updating this file! - Debug.Assert(ExtendedClrTypeCode.First == 0 && (int)ExtendedClrTypeCode.Last == s_canAccessSetterDirectly.GetLength(0) - 1, "ExtendedClrTypeCodes does not match with __canAccessSetterDirectly"); - Debug.Assert(SqlDbType.BigInt == 0 && (int)SqlDbType.DateTimeOffset == s_canAccessSetterDirectly.GetLength(1) - 1, "SqlDbType does not match with __canAccessSetterDirectly"); - Debug.Assert(ExtendedClrTypeCode.First <= setterTypeCode && ExtendedClrTypeCode.Last >= setterTypeCode); - Debug.Assert(SqlDbType.BigInt <= metaData.SqlDbType && SqlDbType.DateTimeOffset >= metaData.SqlDbType); - - bool returnValue = s_canAccessSetterDirectly[(int)setterTypeCode, (int)metaData.SqlDbType]; - - // Additional restrictions to distinguish TVPs and Structured UDTs - if (returnValue && - (ExtendedClrTypeCode.DataTable == setterTypeCode || - ExtendedClrTypeCode.DbDataReader == setterTypeCode || - ExtendedClrTypeCode.IEnumerableOfSqlDataRecord == setterTypeCode)) - { - returnValue = metaData.IsMultiValued; - } - - return returnValue; - } - - private static long PositiveMin(long first, long second) - { - if (first < 0) - { - return second; - } - - if (second < 0) - { - return first; - } - - return Math.Min(first, second); - } - - // Check Get Byte/Chars parameters, throw or adjust invalid values - private static int CheckXetParameters( - SqlDbType dbType, - long maxLength, - long actualLength, - long fieldOffset, - int bufferLength, - int bufferOffset, - int length) - { - if (0 > fieldOffset) - throw ADP.NegativeParameter(nameof(fieldOffset)); - - // if negative buffer index, throw - if (bufferOffset < 0) - { - throw ADP.InvalidDestinationBufferIndex(bufferLength, bufferOffset, nameof(bufferOffset)); - } - - // skip further length checks for LOB buffer lengths - if (bufferLength < 0) - { - length = checked((int)PositiveMin(length, PositiveMin(maxLength, actualLength))); - if (length < NoLengthLimit) - { - length = NoLengthLimit; - } - return length; - } - - // if bad buffer index, throw - if (bufferOffset > bufferLength) - { - throw ADP.InvalidDestinationBufferIndex(bufferLength, bufferOffset, nameof(bufferOffset)); - } - - // if there is not enough room in the buffer for data - if (checked(length + bufferOffset) > bufferLength) - throw ADP.InvalidBufferSizeOrIndex(length, bufferOffset); - - if (length < 0) - throw ADP.InvalidDataLength(length); - - if (0 <= actualLength && actualLength <= fieldOffset) - { - return 0; - } - - // trim length against both bufferLength and actual or max length - // (actual or max < 0 means don't trim against that value) - // Note that parameter UDTs don't know the correct maxlength, so the back end does - // the trimming. Actual length should still be trimmed against here, though. - length = Math.Min(length, bufferLength - bufferOffset); - - // special case for variants, since their maxLength is actually a bit bigger than - // the actual data length allowed. - if (SqlDbType.Variant == dbType) - { - length = Math.Min(length, TdsEnums.TYPE_SIZE_LIMIT); - } - - Debug.Assert(0 > maxLength || 0 > actualLength || - maxLength >= actualLength, "Actual = " + actualLength + ", max = " + maxLength + ", sqldbtype=" + dbType); - - if (0 <= actualLength) - { - // Length is guaranteed to be >= 0 coming in and actualLength >= fieldOffset, so this operation guarantees result >= 0 - length = (int)Math.Min((long)length, actualLength - fieldOffset); - Debug.Assert(length >= 0, "result < 0, actualLength/fieldOffset problem?"); - } - else if (SqlDbType.Udt != dbType && 0 <= maxLength) - { - length = (int)Math.Min((long)length, maxLength - fieldOffset); - Debug.Assert(length >= 0, "Result < 0, maxlen/fieldoffset problem?"); - } - - if (length < 0) - { - return 0; - } - else - { - return length; - } - } - - // - // These tables are formal encoding of the "unchecked" method access rules for various types - // The tables should only be accessed from the CanAccessXetterDirectly methods. - // - - // A couple of private constants to increase the getter/setter access tables' constrast - private const bool X = true; - private const bool _ = false; - - private static bool[,] s_canAccessGetterDirectly = { - // SqlDbTypes as columns (abbreviated, but in order) - // ExtendedClrTypeCodes as rows - - // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO -/*Bool*/ { _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Bool*/ -/*Byte*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Byte*/ -/*Char*/ { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Char*/ -/*DTime*/{ _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*DateTime*/ -/*DBNul*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*DBNull*/ -/*Decim*/{ _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Decimal*/ -/*Doubl*/{ _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Double*/ -/*Empty*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Empty*/ -/*Int16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int16*/ -/*Int32*/{ _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int32*/ -/*Int64*/{ X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int64*/ -/*SByte*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SByte*/ -/*Singl*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Single*/ -/*Strng*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*String*/ -/*UIn16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt16*/ -/*UIn32*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt32*/ -/*UIn64*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt64*/ -/*Objct*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*Object*/ -/*BytAr*/{ _ , X , _ , X , _ , _ , _ , X , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , X , _ , X , X , _ , _ , X , _ , _ , _ , X , _, _ , _ , _ , _ , },/*ByteArray*/ -/*ChrAr*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*CharArray*/ -/*Guid*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Guid*/ -/*SBin*/ { _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBinary*/ -/*SBool*/{ _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlBoolean*/ -/*SByte*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlByte*/ -/*SDTme*/{ _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*SqlDateTime*/ -/*SDubl*/{ _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDouble*/ -/*SGuid*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlGuid*/ -/*SIn16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt16*/ -/*SIn32*/{ _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt32*/ -/*SIn64*/{ X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt64*/ -/*SMony*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlMoney*/ -/*SDeci*/{ _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDecimal*/ -/*SSngl*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlSingle*/ -/*SStrn*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlString*/ -/*SChrs*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlChars*/ -/*SByts*/{ _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBytes*/ -/*SXml*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlXml*/ -/*DTbl*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DataTable*/ -/*Rdr */ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DbDataReader*/ -/*EnSDR*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*IEnurerable*/ -/*TmSpn*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , X , _ , _ , },/*TimeSpan*/ -/*DTOst*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , X , },/*DateTimeOffset*/ -/*Strm */{ _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*Stream*/ -/*TxRdr*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*TextReader*/ -/*XmlRd*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*XmlReader*/ - // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO - }; - - private static bool[,] s_canAccessSetterDirectly = { - // Setters as columns (labels are abreviated from ExtendedClrTypeCode names) - // SqlDbTypes as rows - // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO -/*Bool*/ { _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Bool*/ -/*Byte*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Byte*/ -/*Char*/ { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Char*/ -/*DTime*/{ _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*DateTime*/ -/*DBNul*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*DBNull*/ -/*Decim*/{ _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Decimal*/ -/*Doubl*/{ _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Double*/ -/*Empty*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Empty*/ -/*Int16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int16*/ -/*Int32*/{ _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int32*/ -/*Int64*/{ X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int64*/ -/*SByte*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SByte*/ -/*Singl*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Single*/ -/*Strng*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*String*/ -/*UIn16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt16*/ -/*UIn32*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt32*/ -/*UIn64*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt64*/ -/*Objct*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*Object*/ -/*BytAr*/{ _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , X , _ , X , _ , _ , _ , X , _, _ , _ , _ , _ , },/*ByteArray*/ -/*ChrAr*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*CharArray*/ -/*Guid*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Guid*/ -/*SBin*/ { _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , X , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBinary*/ -/*SBool*/{ _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlBoolean*/ -/*SByte*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlByte*/ -/*SDTme*/{ _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*SqlDateTime*/ -/*SDubl*/{ _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDouble*/ -/*SGuid*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlGuid*/ -/*SIn16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt16*/ -/*SIn32*/{ _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt32*/ -/*SIn64*/{ X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt64*/ -/*SMony*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlMoney*/ -/*SDeci*/{ _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDecimal*/ -/*SSngl*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlSingle*/ -/*SStrn*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlString*/ -/*SChrs*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlChars*/ -/*SByts*/{ _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , X , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBytes*/ -/*SXml*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlXml*/ -/*DTbl*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DataTable*/ -/*Rdr */ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DbDataReader*/ -/*EnSDR*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*IEnurerable*/ -/*TmSpn*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , X , _ , _ , },/*TimeSpan*/ -/*DTOst*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , X , },/*DateTimeOffset*/ -/*Strm */{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Stream*/ -/*TxRdr*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*TextReader*/ -/*XmlRd*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*XmlReader*/ - // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO - }; - - - // - // Private implementation of common mappings from a given type to corresponding Smi Getter/Setter - // These classes do type validation, parameter limit validation, nor coercions - // - private static bool IsDBNull_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - bool result = getters.IsDBNull(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static bool GetBoolean_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - bool result = getters.GetBoolean(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static byte GetByte_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - byte result = getters.GetByte(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static byte[] GetByteArray_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - long length = getters.GetBytesLength(sink, ordinal); - sink.ProcessMessagesAndThrow(); - int len = checked((int)length); - - byte[] buffer = new byte[len]; - getters.GetBytes(sink, ordinal, 0, buffer, 0, len); - sink.ProcessMessagesAndThrow(); - return buffer; - } - - internal static int GetBytes_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - Debug.Assert(ordinal >= 0, $"Invalid ordinal: {ordinal}"); - Debug.Assert(sink != null, "Null SmiEventSink"); - Debug.Assert(getters != null, "Null getters"); - Debug.Assert(fieldOffset >= 0, $"Invalid field offset: {fieldOffset}"); - Debug.Assert(buffer != null, "Null buffer"); - Debug.Assert(bufferOffset >= 0 && length >= 0 && bufferOffset + length <= buffer.Length, $"Bad offset or length. bufferOffset: {bufferOffset}, length: {length}, buffer.Length{buffer.Length}"); - - int result = getters.GetBytes(sink, ordinal, fieldOffset, buffer, bufferOffset, length); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static long GetBytesLength_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - long result = getters.GetBytesLength(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - - private static char[] GetCharArray_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - long length = getters.GetCharsLength(sink, ordinal); - sink.ProcessMessagesAndThrow(); - int len = checked((int)length); - - char[] buffer = new char[len]; - getters.GetChars(sink, ordinal, 0, buffer, 0, len); - sink.ProcessMessagesAndThrow(); - return buffer; - } - - internal static int GetChars_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - Debug.Assert(ordinal >= 0, $"Invalid ordinal: {ordinal}"); - Debug.Assert(sink != null, "Null SmiEventSink"); - Debug.Assert(getters != null, "Null getters"); - Debug.Assert(fieldOffset >= 0, $"Invalid field offset: {fieldOffset}"); - Debug.Assert(buffer != null, "Null buffer"); - Debug.Assert(bufferOffset >= 0 && length >= 0 && bufferOffset + length <= buffer.Length, $"Bad offset or length. bufferOffset: {bufferOffset}, length: {length}, buffer.Length{buffer.Length}"); - - int result = getters.GetChars(sink, ordinal, fieldOffset, buffer, bufferOffset, length); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static long GetCharsLength_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - long result = getters.GetCharsLength(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static DateTime GetDateTime_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - DateTime result = getters.GetDateTime(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static DateTimeOffset GetDateTimeOffset_Unchecked(SmiEventSink_Default sink, SmiTypedGetterSetter getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - DateTimeOffset result = getters.GetDateTimeOffset(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static double GetDouble_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - double result = getters.GetDouble(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static Guid GetGuid_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - Guid result = getters.GetGuid(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static short GetInt16_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - short result = getters.GetInt16(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static int GetInt32_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - int result = getters.GetInt32(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static long GetInt64_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - long result = getters.GetInt64(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static float GetSingle_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - float result = getters.GetSingle(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static SqlBinary GetSqlBinary_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - byte[] buffer = GetByteArray_Unchecked(sink, getters, ordinal); - return new SqlBinary(buffer); - } - - private static SqlDecimal GetSqlDecimal_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - SqlDecimal result = getters.GetSqlDecimal(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static SqlMoney GetSqlMoney_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - long temp = getters.GetInt64(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return SqlTypeWorkarounds.SqlMoneyCtor(temp, 1 /* ignored */ ); - } - - private static SqlXml GetSqlXml_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiContext context) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - // allow context to be null so strongly-typed getters can use - // this method without having to pass along the almost-never-used context as a parameter - // Looking the context up like this will be slightly slower, but still correct behavior - // since it's only used to get a scratch stream. - if (null == context && InOutOfProcHelper.InProc) - { - context = SmiContextFactory.Instance.GetCurrentContext(); // In the future we need to push the context checking to a higher level - } - - // Note: must make a copy of getter stream, since it will be used beyond - // this method (valid lifetime of getters is limited). - Stream s = new SmiGettersStream(sink, getters, ordinal, SmiMetaData.DefaultXml); - Stream copy = ValueUtilsSmi.CopyIntoNewSmiScratchStream(s, sink, context); - SqlXml result = new SqlXml(copy); - return result; - } - - private static String GetString_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - // Note: depending on different getters, the result string maybed truncated, e.g. for - // Inproc process, the getter is InProcRecordBuffer (implemented in SqlAcess), string will be - // truncated to 4000 (if length is more than 4000). If MemoryRecordBuffer getter is used, data - // is not truncated. Please refer VSDD 479655 for more detailed information regarding the string length. - String result = getters.GetString(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static TimeSpan GetTimeSpan_Unchecked(SmiEventSink_Default sink, SmiTypedGetterSetter getters, int ordinal) - { - Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - TimeSpan result = getters.GetTimeSpan(sink, ordinal); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static void SetBoolean_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, bool value) - { - setters.SetBoolean(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetByteArray_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, byte[] buffer, int bufferOffset, int length) - { - if (length > 0) - { - setters.SetBytes(sink, ordinal, 0, buffer, bufferOffset, length); - sink.ProcessMessagesAndThrow(); - } - setters.SetBytesLength(sink, ordinal, length); - sink.ProcessMessagesAndThrow(); - } - - private static void SetStream_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metadata, StreamDataFeed feed) - { - long len = metadata.MaxLength; - byte[] buff = new byte[constBinBufferSize]; - int nWritten = 0; - do - { - int nRead = 0; - int readSize = constBinBufferSize; - if (len > 0 && nWritten + readSize > len) - { - readSize = (int)(len - nWritten); - } - - Debug.Assert(readSize >= 0); - - nRead = feed._source.Read(buff, 0, readSize); - - if (nRead == 0) - { - break; - } - - setters.SetBytes(sink, ordinal, nWritten, buff, 0, nRead); - sink.ProcessMessagesAndThrow(); - - nWritten += nRead; - } while (len <= 0 || nWritten < len); - - setters.SetBytesLength(sink, ordinal, nWritten); - sink.ProcessMessagesAndThrow(); - } - - private static void SetTextReader_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metadata, TextDataFeed feed) - { - long len = metadata.MaxLength; - char[] buff = new char[constTextBufferSize]; - int nWritten = 0; - do - { - int nRead = 0; - int readSize = constTextBufferSize; - if (len > 0 && nWritten + readSize > len) - { - readSize = (int)(len - nWritten); - } - - Debug.Assert(readSize >= 0); - - nRead = feed._source.Read(buff, 0, readSize); - - if (nRead == 0) - { - break; - } - - setters.SetChars(sink, ordinal, nWritten, buff, 0, nRead); - sink.ProcessMessagesAndThrow(); - - nWritten += nRead; - } while (len <= 0 || nWritten < len); - - setters.SetCharsLength(sink, ordinal, nWritten); - sink.ProcessMessagesAndThrow(); - } - - private static void SetByte_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, byte value) - { - setters.SetByte(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static int SetBytes_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length) - { - int result = setters.SetBytes(sink, ordinal, fieldOffset, buffer, bufferOffset, length); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static void SetCharArray_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, char[] buffer, int bufferOffset, int length) - { - if (length > 0) - { - setters.SetChars(sink, ordinal, 0, buffer, bufferOffset, length); - sink.ProcessMessagesAndThrow(); - } - setters.SetCharsLength(sink, ordinal, length); - sink.ProcessMessagesAndThrow(); - } - - private static int SetChars_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length) - { - int result = setters.SetChars(sink, ordinal, fieldOffset, buffer, bufferOffset, length); - sink.ProcessMessagesAndThrow(); - return result; - } - - private static void SetDBNull_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal) - { - setters.SetDBNull(sink, ordinal); - sink.ProcessMessagesAndThrow(); - } - - private static void SetDecimal_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, decimal value) - { - setters.SetSqlDecimal(sink, ordinal, new SqlDecimal(value)); - sink.ProcessMessagesAndThrow(); - } - - private static void SetDateTime_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, DateTime value) - { - setters.SetDateTime(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetDateTime2_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTime value) - { - Debug.Assert(SqlDbType.Variant == metaData.SqlDbType, "Invalid type. This should be called only when the type is variant."); - setters.SetVariantMetaData(sink, ordinal, SmiMetaData.DefaultDateTime2); - setters.SetDateTime(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetDate_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTime value) - { - Debug.Assert(SqlDbType.Variant == metaData.SqlDbType, "Invalid type. This should be called only when the type is variant."); - setters.SetVariantMetaData(sink, ordinal, SmiMetaData.DefaultDate); - setters.SetDateTime(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetTimeSpan_Unchecked(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, TimeSpan value) - { - setters.SetTimeSpan(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetDateTimeOffset_Unchecked(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, DateTimeOffset value) - { - setters.SetDateTimeOffset(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetDouble_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, double value) - { - setters.SetDouble(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetGuid_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, Guid value) - { - setters.SetGuid(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetInt16_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, short value) - { - setters.SetInt16(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetInt32_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, int value) - { - setters.SetInt32(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetInt64_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, long value) - { - setters.SetInt64(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetSingle_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, float value) - { - setters.SetSingle(sink, ordinal, value); - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlBinary_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlBinary value, int offset, int length) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - SetByteArray_Unchecked(sink, setters, ordinal, value.Value, offset, length); - } - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlBoolean_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlBoolean value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - setters.SetBoolean(sink, ordinal, value.Value); - } - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlByte_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlByte value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - setters.SetByte(sink, ordinal, value.Value); - } - sink.ProcessMessagesAndThrow(); - } - - // note: length < 0 indicates write everything - private static void SetSqlBytes_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlBytes value, int offset, long length) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - sink.ProcessMessagesAndThrow(); - } - else - { - int chunkSize; - if (length > __maxByteChunkSize || length < 0) - { - chunkSize = __maxByteChunkSize; - } - else - { - chunkSize = checked((int)length); - } - - byte[] buffer = new byte[chunkSize]; - long bytesRead; - long bytesWritten = 1; // prime value to get into write loop - long currentOffset = offset; - long lengthWritten = 0; - - while ((length < 0 || lengthWritten < length) && - 0 != (bytesRead = value.Read(currentOffset, buffer, 0, chunkSize)) && - 0 != bytesWritten) - { - bytesWritten = setters.SetBytes(sink, ordinal, currentOffset, buffer, 0, checked((int)bytesRead)); - sink.ProcessMessagesAndThrow(); - checked - { - currentOffset += bytesWritten; - } - checked - { - lengthWritten += bytesWritten; - } - } - - // Make sure to trim any left-over data - setters.SetBytesLength(sink, ordinal, currentOffset); - sink.ProcessMessagesAndThrow(); - } - } - - private static void SetSqlChars_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlChars value, int offset, int length) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - sink.ProcessMessagesAndThrow(); - } - else - { - int chunkSize; - if (length > __maxCharChunkSize || length < 0) - { - chunkSize = __maxCharChunkSize; - } - else - { - chunkSize = checked((int)length); - } - - char[] buffer = new char[chunkSize]; - long charsRead; - long charsWritten = 1; // prime value to get into write loop - long currentOffset = offset; - long lengthWritten = 0; - - while ((length < 0 || lengthWritten < length) && - 0 != (charsRead = value.Read(currentOffset, buffer, 0, chunkSize)) && - 0 != charsWritten) - { - charsWritten = setters.SetChars(sink, ordinal, currentOffset, buffer, 0, checked((int)charsRead)); - sink.ProcessMessagesAndThrow(); - checked - { - currentOffset += charsWritten; - } - checked - { - lengthWritten += charsWritten; - } - } - - // Make sure to trim any left-over data - setters.SetCharsLength(sink, ordinal, currentOffset); - sink.ProcessMessagesAndThrow(); - } - } - - private static void SetSqlDateTime_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlDateTime value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - setters.SetDateTime(sink, ordinal, value.Value); - } - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlDecimal_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlDecimal value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - setters.SetSqlDecimal(sink, ordinal, value); - } - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlDouble_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlDouble value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - setters.SetDouble(sink, ordinal, value.Value); - } - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlGuid_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlGuid value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - setters.SetGuid(sink, ordinal, value.Value); - } - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlInt16_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlInt16 value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - setters.SetInt16(sink, ordinal, value.Value); - } - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlInt32_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlInt32 value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - setters.SetInt32(sink, ordinal, value.Value); - } - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlInt64_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlInt64 value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - setters.SetInt64(sink, ordinal, value.Value); - } - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlMoney_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlMoney value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - if (SqlDbType.Variant == metaData.SqlDbType) - { - setters.SetVariantMetaData(sink, ordinal, SmiMetaData.DefaultMoney); - sink.ProcessMessagesAndThrow(); - } - - setters.SetInt64(sink, ordinal, SqlTypeWorkarounds.SqlMoneyToSqlInternalRepresentation(value)); - } - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlSingle_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlSingle value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - } - else - { - setters.SetSingle(sink, ordinal, value.Value); - } - sink.ProcessMessagesAndThrow(); - } - - private static void SetSqlString_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlString value, int offset, int length) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - sink.ProcessMessagesAndThrow(); - } - else - { - if (SqlDbType.Variant == metaData.SqlDbType) - { - // Set up a NVarChar metadata with correct LCID/Collation - metaData = new SmiMetaData( - SqlDbType.NVarChar, - SmiMetaData.MaxUnicodeCharacters, - 0, - 0, - value.LCID, - value.SqlCompareOptions, - null); - setters.SetVariantMetaData(sink, ordinal, metaData); - sink.ProcessMessagesAndThrow(); - } - SetString_Unchecked(sink, setters, ordinal, value.Value, offset, length); - } - } - - private static void SetSqlXml_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SqlXml value) - { - if (value.IsNull) - { - setters.SetDBNull(sink, ordinal); - sink.ProcessMessagesAndThrow(); - } - else - { - SetXmlReader_Unchecked(sink, setters, ordinal, value.CreateReader()); - } - } - - private static void SetXmlReader_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, XmlReader xmlReader) - { - // set up writer - XmlWriterSettings WriterSettings = new XmlWriterSettings(); - WriterSettings.CloseOutput = false; // don't close the memory stream - WriterSettings.ConformanceLevel = ConformanceLevel.Fragment; - WriterSettings.Encoding = System.Text.Encoding.Unicode; - WriterSettings.OmitXmlDeclaration = true; - - System.IO.Stream target = new SmiSettersStream(sink, setters, ordinal, SmiMetaData.DefaultXml); - - XmlWriter xmlWriter = XmlWriter.Create(target, WriterSettings); - - // now spool the data into the writer (WriteNode will call Read()) - xmlReader.Read(); - while (!xmlReader.EOF) - { - xmlWriter.WriteNode(xmlReader, true); - } - xmlWriter.Flush(); - sink.ProcessMessagesAndThrow(); - } - - private static void SetString_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, string value, int offset, int length) - { - setters.SetString(sink, ordinal, value, offset, length); - sink.ProcessMessagesAndThrow(); - } - - private static void SetDataTable_Unchecked( - SmiEventSink_Default sink, - SmiTypedGetterSetter setters, - int ordinal, - SmiMetaData metaData, - DataTable value - ) - { - // Get the target gettersetter - setters = setters.GetTypedGetterSetter(sink, ordinal); - sink.ProcessMessagesAndThrow(); - - // iterate over all records - // if first record was obtained earlier, use it prior to pulling more - ExtendedClrTypeCode[] cellTypes = new ExtendedClrTypeCode[metaData.FieldMetaData.Count]; - for (int i = 0; i < metaData.FieldMetaData.Count; i++) - { - cellTypes[i] = ExtendedClrTypeCode.Invalid; - } - foreach (DataRow row in value.Rows) - { - setters.NewElement(sink); - sink.ProcessMessagesAndThrow(); - - // Set all columns in the record - for (int i = 0; i < metaData.FieldMetaData.Count; i++) - { - SmiMetaData fieldMetaData = metaData.FieldMetaData[i]; - if (row.IsNull(i)) - { - SetDBNull_Unchecked(sink, setters, i); - } - else - { - object cellValue = row[i]; - - // Only determine cell types for first row, to save expensive - if (ExtendedClrTypeCode.Invalid == cellTypes[i]) - { - cellTypes[i] = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType( - fieldMetaData.SqlDbType, fieldMetaData.IsMultiValued, cellValue, fieldMetaData.Type, - // TODO: this version works for shipping Orcas, since only Katmai supports TVPs at this time. - // Need a better story for smi versioning of ValueUtilsSmi post-Orcas - SmiContextFactory.KatmaiVersion - ); - } - SetCompatibleValueV200(sink, setters, i, fieldMetaData, cellValue, cellTypes[i], 0, NoLengthLimit, null); - } - } - } - - setters.EndElements(sink); - sink.ProcessMessagesAndThrow(); - } - - // Set a DbDataReader to a Structured+MultiValued setter (table type) - // Assumes metaData correctly describes the reader's shape, and consumes only the current resultset - private static void SetDbDataReader_Unchecked( - SmiEventSink_Default sink, - SmiTypedGetterSetter setters, - int ordinal, - SmiMetaData metaData, - DbDataReader value - ) - { - // Get the target gettersetter - setters = setters.GetTypedGetterSetter(sink, ordinal); - sink.ProcessMessagesAndThrow(); - - // Iterate over all rows in the current set of results - while (value.Read()) - { - setters.NewElement(sink); - sink.ProcessMessagesAndThrow(); - - FillCompatibleSettersFromReader(sink, setters, metaData.FieldMetaData, value); - } - - setters.EndElements(sink); - sink.ProcessMessagesAndThrow(); - } - - private static void SetIEnumerableOfSqlDataRecord_Unchecked( - SmiEventSink_Default sink, - SmiTypedGetterSetter setters, - int ordinal, - SmiMetaData metaData, - IEnumerable value, - ParameterPeekAheadValue peekAhead - ) - { - // Get target gettersetter - setters = setters.GetTypedGetterSetter(sink, ordinal); - sink.ProcessMessagesAndThrow(); - - IEnumerator enumerator = null; - try - { - // Need to copy field metadata to an array to call FillCompatibleITypeSettersFromRecord - SmiExtendedMetaData[] mdFields = new SmiExtendedMetaData[metaData.FieldMetaData.Count]; - metaData.FieldMetaData.CopyTo(mdFields, 0); - - SmiDefaultFieldsProperty defaults = (SmiDefaultFieldsProperty)metaData.ExtendedProperties[SmiPropertySelector.DefaultFields]; - - int recordNumber = 1; // used only for reporting position when there are errors. - - // obtain enumerator and handle any peekahead values - if (null != peekAhead && null != peekAhead.FirstRecord) - { - // hook up to enumerator - enumerator = peekAhead.Enumerator; - - // send the first record that was obtained earlier - setters.NewElement(sink); - sink.ProcessMessagesAndThrow(); - FillCompatibleSettersFromRecord(sink, setters, mdFields, peekAhead.FirstRecord, defaults); - recordNumber++; - } - else - { - enumerator = value.GetEnumerator(); - } - - using (enumerator) - { - while (enumerator.MoveNext()) - { - setters.NewElement(sink); - sink.ProcessMessagesAndThrow(); - - SqlDataRecord record = enumerator.Current; - - if (record.FieldCount != mdFields.Length) - { - throw SQL.EnumeratedRecordFieldCountChanged(recordNumber); - } - - for (int i = 0; i < record.FieldCount; i++) - { - if (!MetaDataUtilsSmi.IsCompatible(metaData.FieldMetaData[i], record.GetSqlMetaData(i))) - { - throw SQL.EnumeratedRecordMetaDataChanged(record.GetName(i), recordNumber); - } - } - - FillCompatibleSettersFromRecord(sink, setters, mdFields, record, defaults); - recordNumber++; - } - - setters.EndElements(sink); - sink.ProcessMessagesAndThrow(); - } - } - finally - { - // Clean up! - IDisposable disposable = enumerator as IDisposable; - if (null != disposable) - { - disposable.Dispose(); - } - } - } - } -} - diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommandBuilder.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommandBuilder.cs deleted file mode 100644 index 11839689f5..0000000000 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommandBuilder.cs +++ /dev/null @@ -1,415 +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.ComponentModel; -using System.Data; -using System.Data.Common; -using System.Diagnostics; -using System.Runtime.CompilerServices; -using Microsoft.Data.Common; -using Microsoft.Data.Sql; - -namespace Microsoft.Data.SqlClient -{ - /// - [DesignerCategory("")] - public sealed class SqlCommandBuilder : DbCommandBuilder - { - - /// - public SqlCommandBuilder() : base() - { - GC.SuppressFinalize(this); - base.QuotePrefix = "["; // initialize base with defaults - base.QuoteSuffix = "]"; - } - - /// - public SqlCommandBuilder(SqlDataAdapter adapter) : this() - { - DataAdapter = adapter; - } - - /// SqlServer only supports CatalogLocation.Start - /// - [ - Browsable(false), - EditorBrowsableAttribute(EditorBrowsableState.Never), - DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), - ] - public override CatalogLocation CatalogLocation - { - get - { - return CatalogLocation.Start; - } - set - { - if (CatalogLocation.Start != value) - { - throw ADP.SingleValuedProperty("CatalogLocation", "Start"); - } - } - } - - /// SqlServer only supports '.' - /// - [ - Browsable(false), - EditorBrowsableAttribute(EditorBrowsableState.Never), - DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), - ] - public override string CatalogSeparator - { - get - { - return "."; - } - set - { - if ("." != value) - { - throw ADP.SingleValuedProperty("CatalogSeparator", "."); - } - } - } - - /// - [ - DefaultValue(null), - ResCategoryAttribute(StringsHelper.ResourceNames.DataCategory_Update), - ResDescriptionAttribute(StringsHelper.ResourceNames.SqlCommandBuilder_DataAdapter), // MDAC 60524 - ] - new public SqlDataAdapter DataAdapter - { - get - { - return (SqlDataAdapter)base.DataAdapter; - } - set - { - base.DataAdapter = value; - } - } - - /// SqlServer only supports '.' - /// - [ - Browsable(false), - EditorBrowsableAttribute(EditorBrowsableState.Never), - DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), - ] - public override string QuotePrefix - { - get - { - return base.QuotePrefix; - } - set - { - if (("[" != value) && ("\"" != value)) - { - throw ADP.DoubleValuedProperty("QuotePrefix", "[", "\""); - } - base.QuotePrefix = value; - } - } - - /// - [ - Browsable(false), - EditorBrowsableAttribute(EditorBrowsableState.Never), - DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), - ] - public override string QuoteSuffix - { - get - { - return base.QuoteSuffix; - } - set - { - if (("]" != value) && ("\"" != value)) - { - throw ADP.DoubleValuedProperty("QuoteSuffix", "]", "\""); - } - base.QuoteSuffix = value; - } - } - - /// - [ - Browsable(false), - EditorBrowsableAttribute(EditorBrowsableState.Never), - DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), - ] - public override string SchemaSeparator - { - get - { - return "."; - } - set - { - if ("." != value) - { - throw ADP.SingleValuedProperty("SchemaSeparator", "."); - } - } - } - - private void SqlRowUpdatingHandler(object sender, SqlRowUpdatingEventArgs ruevent) - { - base.RowUpdatingHandler(ruevent); - } - - /// - new public SqlCommand GetInsertCommand() - { - return (SqlCommand)base.GetInsertCommand(); - } - /// - new public SqlCommand GetInsertCommand(bool useColumnsForParameterNames) - { - return (SqlCommand)base.GetInsertCommand(useColumnsForParameterNames); - } - - /// - new public SqlCommand GetUpdateCommand() - { - return (SqlCommand)base.GetUpdateCommand(); - } - - /// - new public SqlCommand GetUpdateCommand(bool useColumnsForParameterNames) - { - return (SqlCommand)base.GetUpdateCommand(useColumnsForParameterNames); - } - - /// - new public SqlCommand GetDeleteCommand() - { - return (SqlCommand)base.GetDeleteCommand(); - } - - /// - new public SqlCommand GetDeleteCommand(bool useColumnsForParameterNames) - { - return (SqlCommand)base.GetDeleteCommand(useColumnsForParameterNames); - } - - /// - override protected void ApplyParameterInfo(DbParameter parameter, DataRow datarow, StatementType statementType, bool whereClause) - { - SqlParameter p = (SqlParameter)parameter; - object valueType = datarow[SchemaTableColumn.ProviderType]; - p.SqlDbType = (SqlDbType)valueType; - p.Offset = 0; - - if ((p.SqlDbType == SqlDbType.Udt) && !p.SourceColumnNullMapping) - { - p.UdtTypeName = datarow["DataTypeName"] as string; - } - else - { - p.UdtTypeName = String.Empty; - } - - object bvalue = datarow[SchemaTableColumn.NumericPrecision]; - if (DBNull.Value != bvalue) - { - byte bval = (byte)(short)bvalue; - p.PrecisionInternal = ((0xff != bval) ? bval : (byte)0); - } - - bvalue = datarow[SchemaTableColumn.NumericScale]; - if (DBNull.Value != bvalue) - { - byte bval = (byte)(short)bvalue; - p.ScaleInternal = ((0xff != bval) ? bval : (byte)0); - } - } - - /// - override protected string GetParameterName(int parameterOrdinal) - { - return "@p" + parameterOrdinal.ToString(System.Globalization.CultureInfo.InvariantCulture); - } - - /// - override protected string GetParameterName(string parameterName) - { - return "@" + parameterName; - } - - /// - override protected string GetParameterPlaceholder(int parameterOrdinal) - { - return "@p" + parameterOrdinal.ToString(System.Globalization.CultureInfo.InvariantCulture); - } - - private void ConsistentQuoteDelimiters(string quotePrefix, string quoteSuffix) - { - - Debug.Assert(quotePrefix == "\"" || quotePrefix == "["); - if ((("\"" == quotePrefix) && ("\"" != quoteSuffix)) || - (("[" == quotePrefix) && ("]" != quoteSuffix))) - { - throw ADP.InvalidPrefixSuffix(); - } - - } - - /// - static public void DeriveParameters(SqlCommand command) - { // MDAC 65927\ - SqlConnection.ExecutePermission.Demand(); - - if (null == command) - { - throw ADP.ArgumentNull("command"); - } - TdsParser bestEffortCleanupTarget = null; - RuntimeHelpers.PrepareConstrainedRegions(); - try - { -#if DEBUG - TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); - - RuntimeHelpers.PrepareConstrainedRegions(); - try { - tdsReliabilitySection.Start(); -#else - { -#endif - bestEffortCleanupTarget = SqlInternalConnection.GetBestEffortCleanupTarget(command.Connection); - command.DeriveParameters(); - } -#if DEBUG - finally { - tdsReliabilitySection.Stop(); - } -#endif - } - catch (System.OutOfMemoryException e) - { - if (null != command && null != command.Connection) - { - command.Connection.Abort(e); - } - throw; - } - catch (System.StackOverflowException e) - { - if (null != command && null != command.Connection) - { - command.Connection.Abort(e); - } - throw; - } - catch (System.Threading.ThreadAbortException e) - { - if (null != command && null != command.Connection) - { - command.Connection.Abort(e); - } - SqlInternalConnection.BestEffortCleanup(bestEffortCleanupTarget); - throw; - } - } - - - /* private static void GetLiteralInfo (DataRow dataTypeRow, out string literalPrefix, out string literalSuffix) { - - Object tempValue = dataTypeRow[DbMetaDataColumnNames.LiteralPrefix]; - if (tempValue == DBNull.Value) { - literalPrefix = ""; - } - else { - literalPrefix = (string)dataTypeRow[DbMetaDataColumnNames.LiteralPrefix]; - } - tempValue = dataTypeRow[DbMetaDataColumnNames.LiteralSuffix]; - if (tempValue == DBNull.Value) { - literalSuffix = ""; - } - else { - literalSuffix = (string)dataTypeRow[DbMetaDataColumnNames.LiteralSuffix]; - } - } - */ - - /// - protected override DataTable GetSchemaTable(DbCommand srcCommand) - { - SqlCommand sqlCommand = srcCommand as SqlCommand; - SqlNotificationRequest notificationRequest = sqlCommand.Notification; - bool notificationAutoEnlist = sqlCommand.NotificationAutoEnlist; - - sqlCommand.Notification = null; - sqlCommand.NotificationAutoEnlist = false; - - try - { - using (SqlDataReader dataReader = sqlCommand.ExecuteReader(CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo)) - { - return dataReader.GetSchemaTable(); - } - } - finally - { - sqlCommand.Notification = notificationRequest; - sqlCommand.NotificationAutoEnlist = notificationAutoEnlist; - } - - } - - /// - protected override DbCommand InitializeCommand(DbCommand command) - { - SqlCommand cmd = (SqlCommand)base.InitializeCommand(command); - cmd.NotificationAutoEnlist = false; - return cmd; - } - - /// - public override string QuoteIdentifier(string unquotedIdentifier) - { - ADP.CheckArgumentNull(unquotedIdentifier, "unquotedIdentifier"); - string quoteSuffixLocal = QuoteSuffix; - string quotePrefixLocal = QuotePrefix; - ConsistentQuoteDelimiters(quotePrefixLocal, quoteSuffixLocal); - return ADP.BuildQuotedString(quotePrefixLocal, quoteSuffixLocal, unquotedIdentifier); - ; - } - - /// - override protected void SetRowUpdatingHandler(DbDataAdapter adapter) - { - Debug.Assert(adapter is SqlDataAdapter, "!SqlDataAdapter"); - if (adapter == base.DataAdapter) - { // removal case - ((SqlDataAdapter)adapter).RowUpdating -= SqlRowUpdatingHandler; - } - else - { // adding case - ((SqlDataAdapter)adapter).RowUpdating += SqlRowUpdatingHandler; - } - } - - /// - public override string UnquoteIdentifier(string quotedIdentifier) - { - - ADP.CheckArgumentNull(quotedIdentifier, "quotedIdentifier"); - String unquotedIdentifier; - string quoteSuffixLocal = QuoteSuffix; - string quotePrefixLocal = QuotePrefix; - ConsistentQuoteDelimiters(quotePrefixLocal, quoteSuffixLocal); - // ignoring the return value becasue an unquoted source string is OK here - ADP.RemoveStringQuotes(quotePrefixLocal, quoteSuffixLocal, quotedIdentifier, out unquotedIdentifier); - return unquotedIdentifier; - } - } -} diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionString.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionString.cs index 52131cb1c0..84d032c389 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionString.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionString.cs @@ -594,15 +594,15 @@ internal SqlConnectionString(string connectionString) : base(connectionString, G if (!string.IsNullOrEmpty(_certificate)) { - if (Authentication == SqlClient.SqlAuthenticationMethod.NotSpecified && !_integratedSecurity) { - _authType = SqlClient.SqlAuthenticationMethod.SqlCertificate; + if (Authentication == SqlAuthenticationMethod.NotSpecified && !_integratedSecurity) { + _authType = SqlAuthenticationMethod.SqlCertificate; } - if (Authentication == SqlClient.SqlAuthenticationMethod.SqlCertificate && (HasUserIdKeyword || HasPasswordKeyword || _integratedSecurity)) { + if (Authentication == SqlAuthenticationMethod.SqlCertificate && (_hasUserIdKeyword || _hasPasswordKeyword || _integratedSecurity)) { throw SQL.InvalidCertAuth(); } } - else if (Authentication == SqlClient.SqlAuthenticationMethod.SqlCertificate) { + else if (Authentication == SqlAuthenticationMethod.SqlCertificate) { throw ADP.InvalidConnectionOptionValue(KEY.Authentication); } #endif diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs index 19bec77b80..ddf8feae2e 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionStringBuilder.cs @@ -5,6 +5,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.ComponentModel; using System.Data; using System.Data.Common; @@ -1178,13 +1179,7 @@ public override bool IsFixedSize } /// - public override ICollection Keys - { - get - { - return new Microsoft.Data.Common.ReadOnlyCollection(_validKeywords); - } - } + public override ICollection Keys => new ReadOnlyCollection(_validKeywords); /// public override ICollection Values @@ -1198,7 +1193,7 @@ public override ICollection Values { values[i] = GetAt((Keywords)i); } - return new Microsoft.Data.Common.ReadOnlyCollection(values); + return new ReadOnlyCollection(values); } } diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlDependency.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlDependency.cs deleted file mode 100644 index 938f43e898..0000000000 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlDependency.cs +++ /dev/null @@ -1,1484 +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.Diagnostics; -using System.Globalization; -using System.IO; -using System.Runtime.CompilerServices; -using System.Runtime.Remoting; -using System.Runtime.Serialization; -using System.Runtime.Versioning; -using System.Security.Permissions; -using System.Text; -using System.Threading; -using System.Xml; -using Microsoft.Data.Common; -using Microsoft.Data.ProviderBase; -using Microsoft.Data.Sql; - -namespace Microsoft.Data.SqlClient -{ - /// - public sealed class SqlDependency - { - - // --------------------------------------------------------------------------------------------------------- - // Private class encapsulating the user/identity information - either SQL Auth username or Windows identity. - // --------------------------------------------------------------------------------------------------------- - - internal class IdentityUserNamePair - { - private DbConnectionPoolIdentity _identity; - private string _userName; - - internal IdentityUserNamePair(DbConnectionPoolIdentity identity, string userName) - { - Debug.Assert((identity == null && userName != null) || - (identity != null && userName == null), "Unexpected arguments!"); - _identity = identity; - _userName = userName; - } - - internal DbConnectionPoolIdentity Identity - { - get - { - return _identity; - } - } - - internal string UserName - { - get - { - return _userName; - } - } - - override public bool Equals(object value) - { - IdentityUserNamePair temp = (IdentityUserNamePair)value; - - bool result = false; - - if (null == temp) - { // If passed value null - false. - result = false; - } - else if (this == temp) - { // If instances equal - true. - result = true; - } - else - { - if (_identity != null) - { - if (_identity.Equals(temp._identity)) - { - result = true; - } - } - else if (_userName == temp._userName) - { - result = true; - } - } - - return result; - } - - override public int GetHashCode() - { - int hashValue = 0; - - if (null != _identity) - { - hashValue = _identity.GetHashCode(); - } - else - { - hashValue = _userName.GetHashCode(); - } - - return hashValue; - } - } - // ---------------------------------------- - // END IdentityHashHelper private class. - // ---------------------------------------- - - // ---------------------------------------------------------------------- - // Private class encapsulating the database, service info and hash logic. - // ---------------------------------------------------------------------- - - private class DatabaseServicePair - { - private string _database; - private string _service; // Store the value, but don't use for equality or hashcode! - - internal DatabaseServicePair(string database, string service) - { - Debug.Assert(database != null, "Unexpected argument!"); - _database = database; - _service = service; - } - - internal string Database - { - get - { - return _database; - } - } - - internal string Service - { - get - { - return _service; - } - } - - override public bool Equals(object value) - { - DatabaseServicePair temp = (DatabaseServicePair)value; - - bool result = false; - - if (null == temp) - { // If passed value null - false. - result = false; - } - else if (this == temp) - { // If instances equal - true. - result = true; - } - else if (_database == temp._database) - { - result = true; - } - - return result; - } - - override public int GetHashCode() - { - return _database.GetHashCode(); - } - } - // ---------------------------------------- - // END IdentityHashHelper private class. - // ---------------------------------------- - - // ---------------------------------------------------------------------------- - // Private class encapsulating the event and it's registered execution context. - // ---------------------------------------------------------------------------- - - internal class EventContextPair - { - private OnChangeEventHandler _eventHandler; - private ExecutionContext _context; - private SqlDependency _dependency; - private SqlNotificationEventArgs _args; - - static private ContextCallback _contextCallback = new ContextCallback(InvokeCallback); - - internal EventContextPair(OnChangeEventHandler eventHandler, SqlDependency dependency) - { - Debug.Assert(eventHandler != null && dependency != null, "Unexpected arguments!"); - _eventHandler = eventHandler; - _context = ExecutionContext.Capture(); - _dependency = dependency; - } - - override public bool Equals(object value) - { - EventContextPair temp = (EventContextPair)value; - - bool result = false; - - if (null == temp) - { // If passed value null - false. - result = false; - } - else if (this == temp) - { // If instances equal - true. - result = true; - } - else - { - if (_eventHandler == temp._eventHandler) - { // Handler for same delegates are reference equivalent. - result = true; - } - } - - return result; - } - - override public int GetHashCode() - { - return _eventHandler.GetHashCode(); - } - - internal void Invoke(SqlNotificationEventArgs args) - { - _args = args; - ExecutionContext.Run(_context, _contextCallback, this); - } - - private static void InvokeCallback(object eventContextPair) - { - EventContextPair pair = (EventContextPair)eventContextPair; - pair._eventHandler(pair._dependency, (SqlNotificationEventArgs)pair._args); - } - } - // ---------------------------------------- - // END EventContextPair private class. - // ---------------------------------------- - - //----------------------------------------------- - // Private Class to add ObjRef as DataContract - //----------------------------------------------- - [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.RemotingConfiguration)] - [DataContract] - private class SqlClientObjRef - { - [DataMember] - private static ObjRef s_sqlObjRef; - internal static IRemotingTypeInfo _typeInfo; - - private SqlClientObjRef() { } - - public SqlClientObjRef(SqlDependencyProcessDispatcher dispatcher) : base() - { - s_sqlObjRef = RemotingServices.Marshal(dispatcher); - _typeInfo = s_sqlObjRef.TypeInfo; - } - - internal static bool CanCastToSqlDependencyProcessDispatcher() - { - return _typeInfo.CanCastTo(typeof(SqlDependencyProcessDispatcher), s_sqlObjRef); - } - - internal ObjRef GetObjRef() - { - return s_sqlObjRef; - } - - } - // ------------------------------------------ - // End SqlClientObjRef private class. - // ------------------------------------------- - - // ---------------- - // Instance members - // ---------------- - - // SqlNotificationRequest required state members - - // Only used for SqlDependency.Id. - private readonly string _id = Guid.NewGuid().ToString() + ";" + _appDomainKey; - private string _options; // Concat of service & db, in the form "service=x;local database=y". - private int _timeout; - - // Various SqlDependency required members - private bool _dependencyFired = false; - // SQL BU DT 382314 - we are required to implement our own event collection to preserve ExecutionContext on callback. - private List _eventList = new List(); - private object _eventHandlerLock = new object(); // Lock for event serialization. - // Track the time that this dependency should time out. If the server didn't send a change - // notification or a time-out before this point then the client will perform a client-side - // timeout. - private DateTime _expirationTime = DateTime.MaxValue; - // Used for invalidation of dependencies based on which servers they rely upon. - // It's possible we will over invalidate if unexpected server failure occurs (but not server down). - private List _serverList = new List(); - - // -------------- - // Static members - // -------------- - - private static object _startStopLock = new object(); - private static readonly string _appDomainKey = Guid.NewGuid().ToString(); - // Hashtable containing all information to match from a server, user, database triple to the service started for that - // triple. For each server, there can be N users. For each user, there can be N databases. For each server, user, - // database, there can only be one service. - private static Dictionary>> _serverUserHash = - new Dictionary>>(StringComparer.OrdinalIgnoreCase); - private static SqlDependencyProcessDispatcher _processDispatcher = null; - // The following two strings are used for AppDomain.CreateInstance. - private static readonly string _assemblyName = (typeof(SqlDependencyProcessDispatcher)).Assembly.FullName; - private static readonly string _typeName = (typeof(SqlDependencyProcessDispatcher)).FullName; - - // ----------- - // EventSource members - // ----------- - - private readonly int _objectID = System.Threading.Interlocked.Increment(ref _objectTypeCount); - private static int _objectTypeCount; // EventSource Counter - internal int ObjectID - { - get - { - return _objectID; - } - } - - /// - // ------------ - // Constructors - // ------------ - [System.Security.Permissions.HostProtectionAttribute(ExternalThreading = true)] - public SqlDependency() : this(null, null, SQL.SqlDependencyTimeoutDefault) - { - } - - /// - [System.Security.Permissions.HostProtectionAttribute(ExternalThreading = true)] - public SqlDependency(SqlCommand command) : this(command, null, SQL.SqlDependencyTimeoutDefault) - { - } - - /// - [HostProtection(ExternalThreading = true)] - public SqlDependency(SqlCommand command, string options, int timeout) - { - long scopeID = SqlClientEventSource.Log.TryNotificationScopeEnterEvent(" {0}, options: '{1}', timeout: '{2}'", ObjectID, options, timeout); - try - { - if (InOutOfProcHelper.InProc) - { - throw SQL.SqlDepCannotBeCreatedInProc(); - } - if (timeout < 0) - { - throw SQL.InvalidSqlDependencyTimeout("timeout"); - } - _timeout = timeout; - - if (null != options) - { // Ignore null value - will force to default. - _options = options; - } - - AddCommandInternal(command); - SqlDependencyPerAppDomainDispatcher.SingletonInstance.AddDependencyEntry(this); // Add dep to hashtable with Id. - } - finally - { - SqlClientEventSource.Log.TryNotificationScopeLeaveEvent(scopeID); - } - } - - // ----------------- - // Public Properties - // ----------------- - /// - [ - ResCategoryAttribute(StringsHelper.ResourceNames.DataCategory_Data), - ResDescriptionAttribute(StringsHelper.ResourceNames.SqlDependency_HasChanges) - ] - public bool HasChanges - { - get - { - return _dependencyFired; - } - } - - /// - [ - ResCategoryAttribute(StringsHelper.ResourceNames.DataCategory_Data), - ResDescriptionAttribute(StringsHelper.ResourceNames.SqlDependency_Id) - ] - public string Id - { - get - { - return _id; - } - } - - // ------------------- - // Internal Properties - // ------------------- - - internal static string AppDomainKey - { - get - { - return _appDomainKey; - } - } - - internal DateTime ExpirationTime - { - get - { - return _expirationTime; - } - } - - internal string Options - { - get - { - string result = null; - - if (null != _options) - { - result = _options; - } - - return result; - } - } - - internal static SqlDependencyProcessDispatcher ProcessDispatcher - { - get - { - return _processDispatcher; - } - } - - internal int Timeout - { - get - { - return _timeout; - } - } - - // ------ - // Events - // ------ - /// - [ - ResCategoryAttribute(StringsHelper.ResourceNames.DataCategory_Data), - ResDescriptionAttribute(StringsHelper.ResourceNames.SqlDependency_OnChange) - ] - public event OnChangeEventHandler OnChange - { - // EventHandlers to be fired when dependency is notified. - add - { - long scopeID = SqlClientEventSource.Log.TryNotificationScopeEnterEvent(" {0}", ObjectID); - - try - { - if (null != value) - { - SqlNotificationEventArgs sqlNotificationEvent = null; - - lock (_eventHandlerLock) - { - if (_dependencyFired) - { - // If fired, fire the new event immediately. - SqlClientEventSource.Log.TryNotificationTraceEvent(" Dependency already fired, firing new event."); - sqlNotificationEvent = new SqlNotificationEventArgs(SqlNotificationType.Subscribe, SqlNotificationInfo.AlreadyChanged, SqlNotificationSource.Client); - } - else - { - SqlClientEventSource.Log.TryNotificationTraceEvent(" Dependency has not fired, adding new event."); - EventContextPair pair = new EventContextPair(value, this); - if (!_eventList.Contains(pair)) - { - _eventList.Add(pair); - } - else - { - throw SQL.SqlDependencyEventNoDuplicate(); // SQL BU DT 382314 - } - } - } - - if (null != sqlNotificationEvent) - { // Delay firing the event until outside of lock. - value(this, sqlNotificationEvent); - } - } - } - finally - { - SqlClientEventSource.Log.TryNotificationScopeLeaveEvent(scopeID); - } - } - remove - { - long scopeID = SqlClientEventSource.Log.TryNotificationScopeEnterEvent(" {0}", ObjectID); - try - { - if (null != value) - { - EventContextPair pair = new EventContextPair(value, this); - lock (_eventHandlerLock) - { - int index = _eventList.IndexOf(pair); - if (0 <= index) - { - _eventList.RemoveAt(index); - } - } - } - } - finally - { - SqlClientEventSource.Log.TryNotificationScopeLeaveEvent(scopeID); - } - } - } - - // -------------- - // Public Methods - // -------------- - /// - [ - ResCategoryAttribute(StringsHelper.ResourceNames.DataCategory_Data), - ResDescriptionAttribute(StringsHelper.ResourceNames.SqlDependency_AddCommandDependency) - ] - public void AddCommandDependency(SqlCommand command) - { - // Adds command to dependency collection so we automatically create the SqlNotificationsRequest object - // and listen for a notification for the added commands. - long scopeID = SqlClientEventSource.Log.TryNotificationScopeEnterEvent(" {0}", ObjectID); - try - { - if (command == null) - { - throw ADP.ArgumentNull("command"); - } - - AddCommandInternal(command); - } - finally - { - SqlClientEventSource.Log.TryNotificationScopeLeaveEvent(scopeID); - } - } - - [System.Security.Permissions.ReflectionPermission(System.Security.Permissions.SecurityAction.Assert, MemberAccess = true)] - private static ObjectHandle CreateProcessDispatcher(_AppDomain masterDomain) - { - return masterDomain.CreateInstance(_assemblyName, _typeName); - } - - // ---------------------------------- - // Static Methods - public & internal - // ---------------------------------- - - // Method to obtain AppDomain reference and then obtain the reference to the process wide dispatcher for - // Start() and Stop() method calls on the individual SqlDependency instances. - // SxS: this method retrieves the primary AppDomain stored in native library. Since each System.Data.dll has its own copy of native - // library, this call is safe in SxS - [ResourceExposure(ResourceScope.None)] - [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] - private static void ObtainProcessDispatcher() - { - byte[] nativeStorage = SNINativeMethodWrapper.GetData(); - - if (nativeStorage == null) - { - SqlClientEventSource.Log.TryNotificationTraceEvent(" nativeStorage null, obtaining dispatcher AppDomain and creating ProcessDispatcher."); - -#if DEBUG // Possibly expensive, limit to debug. - SqlClientEventSource.Log.TryNotificationTraceEvent(" AppDomain.CurrentDomain.FriendlyName: {0}", AppDomain.CurrentDomain.FriendlyName); - -#endif - _AppDomain masterDomain = SNINativeMethodWrapper.GetDefaultAppDomain(); - - if (null != masterDomain) - { - ObjectHandle handle = CreateProcessDispatcher(masterDomain); - - if (null != handle) - { - SqlDependencyProcessDispatcher dependency = (SqlDependencyProcessDispatcher)handle.Unwrap(); - - if (null != dependency) - { - _processDispatcher = dependency.SingletonProcessDispatcher; // Set to static instance. - - // Serialize and set in native. - using (MemoryStream stream = new MemoryStream()) - { - SqlClientObjRef objRef = new SqlClientObjRef(_processDispatcher); - DataContractSerializer serializer = new DataContractSerializer(objRef.GetType()); - GetSerializedObject(objRef, serializer, stream); - SNINativeMethodWrapper.SetData(stream.ToArray()); // Native will be forced to synchronize and not overwrite. - } - } - else - { - SqlClientEventSource.Log.TryNotificationTraceEvent(" ERROR - ObjectHandle.Unwrap returned null!"); - throw ADP.InternalError(ADP.InternalErrorCode.SqlDependencyObtainProcessDispatcherFailureObjectHandle); - } - } - else - { - SqlClientEventSource.Log.TryNotificationTraceEvent(" ERROR - AppDomain.CreateInstance returned null!"); - throw ADP.InternalError(ADP.InternalErrorCode.SqlDependencyProcessDispatcherFailureCreateInstance); - } - } - else - { - SqlClientEventSource.Log.TryNotificationTraceEvent(" ERROR - unable to obtain default AppDomain!"); - throw ADP.InternalError(ADP.InternalErrorCode.SqlDependencyProcessDispatcherFailureAppDomain); - } - } - else - { - SqlClientEventSource.Log.TryNotificationTraceEvent(" nativeStorage not null, obtaining existing dispatcher AppDomain and ProcessDispatcher."); - -#if DEBUG // Possibly expensive, limit to debug. - SqlClientEventSource.Log.TryNotificationTraceEvent(" AppDomain.CurrentDomain.FriendlyName: {0}", AppDomain.CurrentDomain.FriendlyName); -#endif - using (MemoryStream stream = new MemoryStream(nativeStorage)) - { - DataContractSerializer serializer = new DataContractSerializer(typeof(SqlClientObjRef)); - if (SqlClientObjRef.CanCastToSqlDependencyProcessDispatcher()) - { - // Deserialize and set for appdomain. - _processDispatcher = GetDeserializedObject(serializer, stream); - } - else - { - throw new ArgumentException(Strings.SqlDependency_UnexpectedValueOnDeserialize); - } - SqlClientEventSource.Log.TryNotificationTraceEvent(" processDispatcher obtained, ID: {0}", _processDispatcher.ObjectID); - } - } - } - - // --------------------------------------------------------- - // Static security asserted methods - limit scope of assert. - // --------------------------------------------------------- - - [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.SerializationFormatter)] - private static void GetSerializedObject(SqlClientObjRef objRef, DataContractSerializer serializer, MemoryStream stream) - { - serializer.WriteObject(stream, objRef); - } - - [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.SerializationFormatter)] - private static SqlDependencyProcessDispatcher GetDeserializedObject(DataContractSerializer serializer, MemoryStream stream) - { - object refResult = serializer.ReadObject(stream); - var result = RemotingServices.Unmarshal((refResult as SqlClientObjRef).GetObjRef()); - return result as SqlDependencyProcessDispatcher; - } - - // ------------------------- - // Static Start/Stop methods - // ------------------------- - /// - [System.Security.Permissions.HostProtectionAttribute(ExternalThreading = true)] - public static bool Start(string connectionString) - { - return Start(connectionString, null, true); - } - - /// - [System.Security.Permissions.HostProtectionAttribute(ExternalThreading = true)] - public static bool Start(string connectionString, string queue) - { - return Start(connectionString, queue, false); - } - - internal static bool Start(string connectionString, string queue, bool useDefaults) - { - long scopeID = SqlClientEventSource.Log.TryNotificationScopeEnterEvent(" AppDomainKey: '{0}', queue: '{1}'", AppDomainKey, queue); - try - { - // The following code exists in Stop as well. It exists here to demand permissions as high in the stack - // as possible. - if (InOutOfProcHelper.InProc) - { - throw SQL.SqlDepCannotBeCreatedInProc(); - } - - if (ADP.IsEmpty(connectionString)) - { - if (null == connectionString) - { - throw ADP.ArgumentNull("connectionString"); - } - else - { - throw ADP.Argument("connectionString"); - } - } - - if (!useDefaults && ADP.IsEmpty(queue)) - { // If specified but null or empty, use defaults. - useDefaults = true; - queue = null; // Force to null - for proper hashtable comparison for default case. - } - - // Create new connection options for demand on their connection string. We modify the connection string - // and assert on our modified string when we create the container. - SqlConnectionString connectionStringObject = new SqlConnectionString(connectionString); - connectionStringObject.DemandPermission(); - if (connectionStringObject.LocalDBInstance != null) - { - LocalDBAPI.DemandLocalDBPermissions(); - } - // End duplicate Start/Stop logic. - - bool errorOccurred = false; - bool result = false; - - lock (_startStopLock) - { - try - { - if (null == _processDispatcher) - { // Ensure _processDispatcher reference is present - inside lock. - ObtainProcessDispatcher(); - } - - if (useDefaults) - { // Default listener. - string server = null; - DbConnectionPoolIdentity identity = null; - string user = null; - string database = null; - string service = null; - bool appDomainStart = false; - - RuntimeHelpers.PrepareConstrainedRegions(); - try - { // CER to ensure that if Start succeeds we add to hash completing setup. - // Start using process wide default service/queue & database from connection string. - result = _processDispatcher.StartWithDefault(connectionString, - out server, - out identity, - out user, - out database, - ref service, - _appDomainKey, - SqlDependencyPerAppDomainDispatcher.SingletonInstance, - out errorOccurred, - out appDomainStart); - - SqlClientEventSource.Log.TryNotificationTraceEvent(" Start (defaults) returned: '{0}', with service: '{1}', server: '{2}', database: '{3}'", result, service, server, database); - } - finally - { - if (appDomainStart && !errorOccurred) - { // If success, add to hashtable. - IdentityUserNamePair identityUser = new IdentityUserNamePair(identity, user); - DatabaseServicePair databaseService = new DatabaseServicePair(database, service); - if (!AddToServerUserHash(server, identityUser, databaseService)) - { - try - { - Stop(connectionString, queue, useDefaults, true); - } - catch (Exception e) - { // Discard stop failure! - if (!ADP.IsCatchableExceptionType(e)) - { - throw; - } - - ADP.TraceExceptionWithoutRethrow(e); // Discard failure, but trace for now. - SqlClientEventSource.Log.TryNotificationTraceEvent(" Exception occurred from Stop() after duplicate was found on Start()."); - } - throw SQL.SqlDependencyDuplicateStart(); - } - } - } - } - else - { // Start with specified service/queue & database. - result = _processDispatcher.Start(connectionString, - queue, - _appDomainKey, - SqlDependencyPerAppDomainDispatcher.SingletonInstance); - SqlClientEventSource.Log.TryNotificationTraceEvent(" Start (user provided queue) returned: '{0}'", result); - - // No need to call AddToServerDatabaseHash since if not using default queue user is required - // to provide options themselves. - } - } - catch (Exception e) - { - if (!ADP.IsCatchableExceptionType(e)) - { - throw; - } - - ADP.TraceExceptionWithoutRethrow(e); // Discard failure, but trace for now. - - SqlClientEventSource.Log.TryNotificationTraceEvent(" Exception occurred from _processDispatcher.Start(...), calling Invalidate(...)."); - throw; - } - } - - return result; - } - finally - { - SqlClientEventSource.Log.TryNotificationScopeLeaveEvent(scopeID); - } - } - - /// - [System.Security.Permissions.HostProtectionAttribute(ExternalThreading = true)] - public static bool Stop(string connectionString) - { - return Stop(connectionString, null, true, false); - } - - /// - [System.Security.Permissions.HostProtectionAttribute(ExternalThreading = true)] - public static bool Stop(string connectionString, string queue) - { - return Stop(connectionString, queue, false, false); - } - - internal static bool Stop(string connectionString, string queue, bool useDefaults, bool startFailed) - { - long scopeID = SqlClientEventSource.Log.TryNotificationScopeEnterEvent(" AppDomainKey: '{0}', queue: '{1}'", AppDomainKey, queue); - try - { - // The following code exists in Stop as well. It exists here to demand permissions as high in the stack - // as possible. - if (InOutOfProcHelper.InProc) - { - throw SQL.SqlDepCannotBeCreatedInProc(); - } - - if (ADP.IsEmpty(connectionString)) - { - if (null == connectionString) - { - throw ADP.ArgumentNull("connectionString"); - } - else - { - throw ADP.Argument("connectionString"); - } - } - - if (!useDefaults && ADP.IsEmpty(queue)) - { // If specified but null or empty, use defaults. - useDefaults = true; - queue = null; // Force to null - for proper hashtable comparison for default case. - } - - // Create new connection options for demand on their connection string. We modify the connection string - // and assert on our modified string when we create the container. - SqlConnectionString connectionStringObject = new SqlConnectionString(connectionString); - connectionStringObject.DemandPermission(); - if (connectionStringObject.LocalDBInstance != null) - { - LocalDBAPI.DemandLocalDBPermissions(); - } - // End duplicate Start/Stop logic. - - bool result = false; - - lock (_startStopLock) - { - if (null != _processDispatcher) - { // If _processDispatcher null, no Start has been called. - try - { - string server = null; - DbConnectionPoolIdentity identity = null; - string user = null; - string database = null; - string service = null; - - if (useDefaults) - { - bool appDomainStop = false; - - RuntimeHelpers.PrepareConstrainedRegions(); - try - { // CER to ensure that if Stop succeeds we remove from hash completing teardown. - // Start using process wide default service/queue & database from connection string. - result = _processDispatcher.Stop(connectionString, - out server, - out identity, - out user, - out database, - ref service, - _appDomainKey, - out appDomainStop); - } - finally - { - if (appDomainStop && !startFailed) - { // If success, remove from hashtable. - Debug.Assert(!ADP.IsEmpty(server) && !ADP.IsEmpty(database), "Server or Database null/Empty upon successful Stop()!"); - IdentityUserNamePair identityUser = new IdentityUserNamePair(identity, user); - DatabaseServicePair databaseService = new DatabaseServicePair(database, service); - RemoveFromServerUserHash(server, identityUser, databaseService); - } - } - } - else - { - bool ignored = false; - result = _processDispatcher.Stop(connectionString, - out server, - out identity, - out user, - out database, - ref queue, - _appDomainKey, - out ignored); - // No need to call RemoveFromServerDatabaseHash since if not using default queue user is required - // to provide options themselves. - } - } - catch (Exception e) - { - if (!ADP.IsCatchableExceptionType(e)) - { - throw; - } - - ADP.TraceExceptionWithoutRethrow(e); // Discard failure, but trace for now. - } - } - } - return result; - } - finally - { - SqlClientEventSource.Log.TryNotificationScopeLeaveEvent(scopeID); - } - } - - // -------------------------------- - // General static utility functions - // -------------------------------- - - private static bool AddToServerUserHash(string server, IdentityUserNamePair identityUser, DatabaseServicePair databaseService) - { - long scopeID = SqlClientEventSource.Log.TryNotificationScopeEnterEvent(" server: '{0}', database: '{1}', service: '{2}'", server, databaseService.Database, databaseService.Service); - try - { - bool result = false; - - lock (_serverUserHash) - { - Dictionary> identityDatabaseHash; - - if (!_serverUserHash.ContainsKey(server)) - { - SqlClientEventSource.Log.TryNotificationTraceEvent(" Hash did not contain server, adding."); - identityDatabaseHash = new Dictionary>(); - _serverUserHash.Add(server, identityDatabaseHash); - } - else - { - identityDatabaseHash = _serverUserHash[server]; - } - - List databaseServiceList; - - if (!identityDatabaseHash.ContainsKey(identityUser)) - { - SqlClientEventSource.Log.TryNotificationTraceEvent(" Hash contained server but not user, adding user."); - databaseServiceList = new List(); - identityDatabaseHash.Add(identityUser, databaseServiceList); - } - else - { - databaseServiceList = identityDatabaseHash[identityUser]; - } - - if (!databaseServiceList.Contains(databaseService)) - { - SqlClientEventSource.Log.TryNotificationTraceEvent(" Adding database."); - databaseServiceList.Add(databaseService); - result = true; - } - else - { - SqlClientEventSource.Log.TryNotificationTraceEvent(" ERROR - hash already contained server, user, and database - we will throw!."); - } - } - - return result; - } - finally - { - SqlClientEventSource.Log.TryNotificationScopeLeaveEvent(scopeID); - } - } - - private static void RemoveFromServerUserHash(string server, IdentityUserNamePair identityUser, DatabaseServicePair databaseService) - { - long scopeID = SqlClientEventSource.Log.TryNotificationScopeEnterEvent(" server: '{0}', database: '{1}', service: '{2}'", server, databaseService.Database, databaseService.Service); - try - { - lock (_serverUserHash) - { - Dictionary> identityDatabaseHash; - - if (_serverUserHash.ContainsKey(server)) - { - identityDatabaseHash = _serverUserHash[server]; - - List databaseServiceList; - - if (identityDatabaseHash.ContainsKey(identityUser)) - { - databaseServiceList = identityDatabaseHash[identityUser]; - - int index = databaseServiceList.IndexOf(databaseService); - if (index >= 0) - { - SqlClientEventSource.Log.TryNotificationTraceEvent(" Hash contained server, user, and database - removing database."); - databaseServiceList.RemoveAt(index); - - if (databaseServiceList.Count == 0) - { - SqlClientEventSource.Log.TryNotificationTraceEvent(" databaseServiceList count 0, removing the list for this server and user."); - identityDatabaseHash.Remove(identityUser); - - if (identityDatabaseHash.Count == 0) - { - SqlClientEventSource.Log.TryNotificationTraceEvent(" identityDatabaseHash count 0, removing the hash for this server."); - _serverUserHash.Remove(server); - } - } - } - else - { - SqlClientEventSource.Log.TryNotificationTraceEvent(" ERROR - hash contained server and user but not database!"); - Debug.Assert(false, "Unexpected state - hash did not contain database!"); - } - } - else - { - SqlClientEventSource.Log.TryNotificationTraceEvent(" ERROR - hash contained server but not user!"); - Debug.Assert(false, "Unexpected state - hash did not contain user!"); - } - } - else - { - SqlClientEventSource.Log.TryNotificationTraceEvent(" ERROR - hash did not contain server!"); - Debug.Assert(false, "Unexpected state - hash did not contain server!"); - } - } - } - finally - { - SqlClientEventSource.Log.TryNotificationScopeLeaveEvent(scopeID); - } - } - - internal static string GetDefaultComposedOptions(string server, string failoverServer, IdentityUserNamePair identityUser, string database) - { - // Server must be an exact match, but user and database only needs to match exactly if there is more than one - // for the given user or database passed. That is ambiguious and we must fail. - long scopeID = SqlClientEventSource.Log.TryNotificationScopeEnterEvent(" server: '{0}', failoverServer: '{1}', database: '{2}'", server, failoverServer, database); - - try - { - string result; - - lock (_serverUserHash) - { - if (!_serverUserHash.ContainsKey(server)) - { - if (0 == _serverUserHash.Count) - { - // Special error for no calls to start. - SqlClientEventSource.Log.TryNotificationTraceEvent(" ERROR - no start calls have been made, about to throw."); - throw SQL.SqlDepDefaultOptionsButNoStart(); - } - else if (!ADP.IsEmpty(failoverServer) && _serverUserHash.ContainsKey(failoverServer)) - { - SqlClientEventSource.Log.TryNotificationTraceEvent(" using failover server instead\n"); - server = failoverServer; - } - else - { - SqlClientEventSource.Log.TryNotificationTraceEvent(" ERROR - not listening to this server, about to throw."); - throw SQL.SqlDependencyNoMatchingServerStart(); - } - } - - Dictionary> identityDatabaseHash = _serverUserHash[server]; - - List databaseList = null; - - if (!identityDatabaseHash.ContainsKey(identityUser)) - { - if (identityDatabaseHash.Count > 1) - { - SqlClientEventSource.Log.TryNotificationTraceEvent(" ERROR - not listening for this user, " + - "but listening to more than one other user, about to throw."); - throw SQL.SqlDependencyNoMatchingServerStart(); - } - else - { - // Since only one user, - use that. - // Foreach - but only one value present. - foreach (KeyValuePair> entry in identityDatabaseHash) - { - databaseList = entry.Value; - break; // Only iterate once. - } - } - } - else - { - databaseList = identityDatabaseHash[identityUser]; - } - - DatabaseServicePair pair = new DatabaseServicePair(database, null); - DatabaseServicePair resultingPair = null; - int index = databaseList.IndexOf(pair); - if (index != -1) - { // Exact match found, use it. - resultingPair = databaseList[index]; - } - - if (null != resultingPair) - { // Exact database match. - database = FixupServiceOrDatabaseName(resultingPair.Database); // Fixup in place. - string quotedService = FixupServiceOrDatabaseName(resultingPair.Service); - result = "Service=" + quotedService + ";Local Database=" + database; - } - else - { // No exact database match found. - if (databaseList.Count == 1) - { // If only one database for this server/user, use it. - object[] temp = databaseList.ToArray(); // Must copy, no other choice but foreach. - resultingPair = (DatabaseServicePair)temp[0]; - Debug.Assert(temp.Length == 1, "If databaseList.Count==1, why does copied array have length other than 1?"); - string quotedDatabase = FixupServiceOrDatabaseName(resultingPair.Database); - string quotedService = FixupServiceOrDatabaseName(resultingPair.Service); - result = "Service=" + quotedService + ";Local Database=" + quotedDatabase; - } - else - { - // More than one database for given server, ambiguous - fail the default case! - SqlClientEventSource.Log.TryNotificationTraceEvent(" ERROR - SqlDependency.Start called multiple times for this server/user, but no matching database."); - throw SQL.SqlDependencyNoMatchingServerDatabaseStart(); - } - } - } - - Debug.Assert(!ADP.IsEmpty(result), "GetDefaultComposedOptions should never return null or empty string!"); - SqlClientEventSource.Log.TryNotificationTraceEvent(" resulting options: '{0}'.", result); - return result; - } - finally - { - SqlClientEventSource.Log.TryNotificationScopeLeaveEvent(scopeID); - } - } - - // ---------------- - // Internal Methods - // ---------------- - - // Called by SqlCommand upon execution of a SqlNotificationRequest class created by this dependency. We - // use this list for a reverse lookup based on server. - internal void AddToServerList(string server) - { - long scopeID = SqlClientEventSource.Log.TryNotificationScopeEnterEvent(" {0}, server: '{1}'", ObjectID, server); - try - { - lock (_serverList) - { - int index = _serverList.BinarySearch(server, StringComparer.OrdinalIgnoreCase); - if (0 > index) - { - // If less than 0, item was not found in list. - SqlClientEventSource.Log.TryNotificationTraceEvent(" Server not present in hashtable, adding server: '{0}'.", server); - index = ~index; // BinarySearch returns the 2's compliment of where the item should be inserted to preserver a sorted list after insertion. - _serverList.Insert(index, server); - } - } - } - finally - { - SqlClientEventSource.Log.TryNotificationScopeLeaveEvent(scopeID); - } - } - - internal bool ContainsServer(string server) - { - lock (_serverList) - { - return _serverList.Contains(server); - } - } - - internal string ComputeHashAndAddToDispatcher(SqlCommand command) - { - long scopeID = SqlClientEventSource.Log.TryNotificationScopeEnterEvent(" {0}, SqlCommand: {1}", ObjectID, command.ObjectID); - try - { - // Create a string representing the concatenation of the connection string, command text and .ToString on all parameter values. - // This string will then be mapped to unique notification ID (new GUID). We add the guid and the hash to the app domain - // dispatcher to be able to map back to the dependency that needs to be fired for a notification of this - // command. - - // VSTS 59821: add Connection string to prevent redundant notifications when same command is running against different databases or SQL servers - // TODO: this solution only mitigates the majority of cases. We do not solve the case where the Connection string and the Command text are the same, - // but Database is different (default DB is assigned to user). In this case, users will still get redundant notifications of each other and the only - // workaround would be changing the command text to have some unique user information. - string commandHash = ComputeCommandHash(command.Connection.ConnectionString, command); // calculate the string representation of command - - string idString = SqlDependencyPerAppDomainDispatcher.SingletonInstance.AddCommandEntry(commandHash, this); // Add to map. - SqlClientEventSource.Log.TryNotificationTraceEvent(" computed id string: '{0}'.", idString); - return idString; - } - finally - { - SqlClientEventSource.Log.TryNotificationScopeLeaveEvent(scopeID); - } - } - - internal void Invalidate(SqlNotificationType type, SqlNotificationInfo info, SqlNotificationSource source) - { - long scopeID = SqlClientEventSource.Log.TryNotificationScopeEnterEvent(" {0}", ObjectID); - try - { - List eventList = null; - - lock (_eventHandlerLock) - { - if (_dependencyFired && - SqlNotificationInfo.AlreadyChanged != info && - SqlNotificationSource.Client != source) - { - - if (ExpirationTime < DateTime.UtcNow) - { - // There is a small window in which SqlDependencyPerAppDomainDispatcher.TimeoutTimerCallback - // raises Timeout event but before removing this event from the list. If notification is received from - // server in this case, we will hit this code path. - // It is safe to ignore this race condition because no event is sent to user and no leak happens. - SqlClientEventSource.Log.TryNotificationTraceEvent(" ignore notification received after timeout!"); - } - else - { - Debug.Assert(false, "Received notification twice - we should never enter this state!"); - SqlClientEventSource.Log.TryNotificationTraceEvent(" ERROR - notification received twice - we should never enter this state!"); - } - } - else - { - // It is the invalidators responsibility to remove this dependency from the app domain static hash. - _dependencyFired = true; - eventList = _eventList; - _eventList = new List(); // Since we are firing the events, null so we do not fire again. - } - } - - if (eventList != null) - { - SqlClientEventSource.Log.TryNotificationTraceEvent(" Firing events."); - foreach (EventContextPair pair in eventList) - { - pair.Invoke(new SqlNotificationEventArgs(type, info, source)); - } - } - } - finally - { - SqlClientEventSource.Log.TryNotificationScopeLeaveEvent(scopeID); - } - } - - // This method is used by SqlCommand. - internal void StartTimer(SqlNotificationRequest notificationRequest) - { - long scopeID = SqlClientEventSource.Log.TryNotificationScopeEnterEvent(" {0}", ObjectID); - try - { - if (_expirationTime == DateTime.MaxValue) - { - SqlClientEventSource.Log.TryNotificationTraceEvent(" We've timed out, executing logic."); - int seconds = SQL.SqlDependencyServerTimeout; - if (0 != _timeout) - { - seconds = _timeout; - } - if (notificationRequest != null && notificationRequest.Timeout < seconds && notificationRequest.Timeout != 0) - { - seconds = notificationRequest.Timeout; - } - - // VSDD 563926: we use UTC to check if SqlDependency is expired, need to use it here as well. - _expirationTime = DateTime.UtcNow.AddSeconds(seconds); - SqlDependencyPerAppDomainDispatcher.SingletonInstance.StartTimer(this); - } - } - finally - { - SqlClientEventSource.Log.TryNotificationScopeLeaveEvent(scopeID); - } - } - - // --------------- - // Private Methods - // --------------- - - private void AddCommandInternal(SqlCommand cmd) - { - if (cmd != null) - { - long scopeID = SqlClientEventSource.Log.TryNotificationScopeEnterEvent(" {0}, SqlCommand: {1}", ObjectID, cmd.ObjectID); - try - { - SqlConnection connection = cmd.Connection; - - if (cmd.Notification != null) - { - // Fail if cmd has notification that is not already associated with this dependency. - if (cmd._sqlDep == null || cmd._sqlDep != this) - { - SqlClientEventSource.Log.TryNotificationTraceEvent(" ERROR - throwing command has existing SqlNotificationRequest exception."); - throw SQL.SqlCommandHasExistingSqlNotificationRequest(); - } - } - else - { - bool needToInvalidate = false; - - lock (_eventHandlerLock) - { - if (!_dependencyFired) - { - cmd.Notification = new SqlNotificationRequest(); - cmd.Notification.Timeout = _timeout; - - // Add the command - A dependancy should always map to a set of commands which haven't fired. - if (null != _options) - { // Assign options if user provided. - cmd.Notification.Options = _options; - } - - cmd._sqlDep = this; - } - else - { - // We should never be able to enter this state, since if we've fired our event list is cleared - // and the event method will immediately fire if a new event is added. So, we should never have - // an event to fire in the event list once we've fired. - Debug.Assert(0 == _eventList.Count, "How can we have an event at this point?"); - if (0 == _eventList.Count) - { - // Keep logic just in case. - SqlClientEventSource.Log.TryNotificationTraceEvent(" ERROR - firing events, though it is unexpected we have events at this point."); - needToInvalidate = true; // Delay invalidation until outside of lock. - } - } - } - - if (needToInvalidate) - { - Invalidate(SqlNotificationType.Subscribe, SqlNotificationInfo.AlreadyChanged, SqlNotificationSource.Client); - } - } - } - finally - { - SqlClientEventSource.Log.TryNotificationScopeLeaveEvent(scopeID); - } - } - } - - private string ComputeCommandHash(string connectionString, SqlCommand command) - { - long scopeID = SqlClientEventSource.Log.TryNotificationScopeEnterEvent(" {0}, SqlCommand: {1}", ObjectID, command.ObjectID); - try - { - // Create a string representing the concatenation of the connection string, the command text and .ToString on all its parameter values. - // This string will then be mapped to the notification ID. - - // All types should properly support a .ToString for the values except - // byte[], char[], and XmlReader. - - // NOTE - I hope this doesn't come back to bite us. :( - StringBuilder builder = new StringBuilder(); - - // add the Connection string and the Command text - builder.AppendFormat("{0};{1}", connectionString, command.CommandText); - - // append params - for (int i = 0; i < command.Parameters.Count; i++) - { - object value = command.Parameters[i].Value; - - if (value == null || value == DBNull.Value) - { - builder.Append("; NULL"); - } - else - { - Type type = value.GetType(); - - if (type == typeof(Byte[])) - { - builder.Append(";"); - byte[] temp = (byte[])value; - for (int j = 0; j < temp.Length; j++) - { - builder.Append(temp[j].ToString("x2", CultureInfo.InvariantCulture)); - } - } - else if (type == typeof(Char[])) - { - builder.Append((char[])value); - } - else if (type == typeof(XmlReader)) - { - builder.Append(";"); - // Cannot .ToString XmlReader - just allocate GUID. - // This means if XmlReader is used, we will not reuse IDs. - builder.Append(Guid.NewGuid().ToString()); - } - else - { - builder.Append(";"); - builder.Append(value.ToString()); - } - } - } - - string result = builder.ToString(); - SqlClientEventSource.Log.TryNotificationTraceEvent(" ComputeCommandHash result: '{0}'.", result); - return result; - } - finally - { - SqlClientEventSource.Log.TryNotificationScopeLeaveEvent(scopeID); - } - } - - // Basic copy of function in SqlConnection.cs for ChangeDatabase and similar functionality. Since this will - // only be used for default service and database provided by server, we do not need to worry about an already - // quoted value. - static internal string FixupServiceOrDatabaseName(string name) - { - if (!ADP.IsEmpty(name)) - { - return "\"" + name.Replace("\"", "\"\"") + "\""; - } - else - { - return name; - } - } - } -} diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlEnums.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlEnums.cs deleted file mode 100644 index 222c25611b..0000000000 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlEnums.cs +++ /dev/null @@ -1,1123 +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.Data; -using System.Data.Common; -using System.Data.OleDb; -using System.Data.SqlTypes; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Xml; -using Microsoft.Data.Common; -using Microsoft.Data.SqlClient.Server; - -namespace Microsoft.Data.SqlClient -{ - internal sealed class MetaType - { - internal readonly Type ClassType; // com+ type - internal readonly Type SqlType; - - internal readonly int FixedLength; // fixed length size in bytes (-1 for variable) - internal readonly bool IsFixed; // true if fixed length, note that sqlchar and sqlbinary are not considered fixed length - internal readonly bool IsLong; // true if long - internal readonly bool IsPlp; // Column is Partially Length Prefixed (MAX) - internal readonly byte Precision; // maxium precision for numeric types // $CONSIDER - are we going to use this? - internal readonly byte Scale; - internal readonly byte TDSType; - internal readonly byte NullableType; - - internal readonly string TypeName; // string name of this type - internal readonly SqlDbType SqlDbType; - internal readonly DbType DbType; - - // holds count of property bytes expected for a SQLVariant structure - internal readonly byte PropBytes; - - - // pre-computed fields - internal readonly bool IsAnsiType; - internal readonly bool IsBinType; - internal readonly bool IsCharType; - internal readonly bool IsNCharType; - internal readonly bool IsSizeInCharacters; - internal readonly bool IsNewKatmaiType; - internal readonly bool IsVarTime; - - internal readonly bool Is70Supported; - internal readonly bool Is80Supported; - internal readonly bool Is90Supported; - internal readonly bool Is100Supported; - - public MetaType(byte precision, byte scale, int fixedLength, bool isFixed, bool isLong, bool isPlp, byte tdsType, byte nullableTdsType, string typeName, Type classType, Type sqlType, SqlDbType sqldbType, DbType dbType, byte propBytes) - { - this.Precision = precision; - this.Scale = scale; - this.FixedLength = fixedLength; - this.IsFixed = isFixed; - this.IsLong = isLong; - this.IsPlp = isPlp; - // can we get rid of this (?just have a mapping?) - this.TDSType = tdsType; - this.NullableType = nullableTdsType; - this.TypeName = typeName; - this.SqlDbType = sqldbType; - this.DbType = dbType; - - this.ClassType = classType; - this.SqlType = sqlType; - this.PropBytes = propBytes; - - IsAnsiType = _IsAnsiType(sqldbType); - IsBinType = _IsBinType(sqldbType); - IsCharType = _IsCharType(sqldbType); - IsNCharType = _IsNCharType(sqldbType); - IsSizeInCharacters = _IsSizeInCharacters(sqldbType); - IsNewKatmaiType = _IsNewKatmaiType(sqldbType); - IsVarTime = _IsVarTime(sqldbType); - - Is70Supported = _Is70Supported(SqlDbType); - Is80Supported = _Is80Supported(SqlDbType); - Is90Supported = _Is90Supported(SqlDbType); - Is100Supported = _Is100Supported(SqlDbType); - } - - // properties should be inlined so there should be no perf penalty for using these accessor functions - public int TypeId - { // partial length prefixed (xml, nvarchar(max),...) - get { return 0; } - } - - private static bool _IsAnsiType(SqlDbType type) - { - return (type == SqlDbType.Char || - type == SqlDbType.VarChar || - type == SqlDbType.Text); - } - - // is this type size expressed as count of characters or bytes? - private static bool _IsSizeInCharacters(SqlDbType type) - { - return (type == SqlDbType.NChar || - type == SqlDbType.NVarChar || - type == SqlDbType.Xml || - type == SqlDbType.NText); - } - - private static bool _IsCharType(SqlDbType type) - { - return (type == SqlDbType.NChar || - type == SqlDbType.NVarChar || - type == SqlDbType.NText || - type == SqlDbType.Char || - type == SqlDbType.VarChar || - type == SqlDbType.Text || - type == SqlDbType.Xml); - } - - private static bool _IsNCharType(SqlDbType type) - { - return (type == SqlDbType.NChar || - type == SqlDbType.NVarChar || - type == SqlDbType.NText || - type == SqlDbType.Xml); - } - - private static bool _IsBinType(SqlDbType type) - { - return (type == SqlDbType.Image || - type == SqlDbType.Binary || - type == SqlDbType.VarBinary || - type == SqlDbType.Timestamp || - type == SqlDbType.Udt || - (int)type == 24 /*SqlSmallVarBinary*/); - } - - private static bool _Is70Supported(SqlDbType type) - { - return ((type != SqlDbType.BigInt) && ((int)type > 0) && - ((int)type <= (int)SqlDbType.VarChar)); - } - - private static bool _Is80Supported(SqlDbType type) - { - return ((int)type >= 0 && - ((int)type <= (int)SqlDbType.Variant)); - } - - private static bool _Is90Supported(SqlDbType type) - { - return _Is80Supported(type) || - SqlDbType.Xml == type || - SqlDbType.Udt == type; - } - - private static bool _Is100Supported(SqlDbType type) - { - return _Is90Supported(type) || - SqlDbType.Date == type || - SqlDbType.Time == type || - SqlDbType.DateTime2 == type || - SqlDbType.DateTimeOffset == type; - } - - private static bool _IsNewKatmaiType(SqlDbType type) - { - return SqlDbType.Structured == type; - } - - internal static bool _IsVarTime(SqlDbType type) - { - return (type == SqlDbType.Time || type == SqlDbType.DateTime2 || type == SqlDbType.DateTimeOffset); - } - - // - // map SqlDbType to MetaType class - // - internal static MetaType GetMetaTypeFromSqlDbType(SqlDbType target, bool isMultiValued) - { // WebData 113289 - switch (target) - { - case SqlDbType.BigInt: - return MetaBigInt; - case SqlDbType.Binary: - return MetaBinary; - case SqlDbType.Bit: - return MetaBit; - case SqlDbType.Char: - return MetaChar; - case SqlDbType.DateTime: - return MetaDateTime; - case SqlDbType.Decimal: - return MetaDecimal; - case SqlDbType.Float: - return MetaFloat; - case SqlDbType.Image: - return MetaImage; - case SqlDbType.Int: - return MetaInt; - case SqlDbType.Money: - return MetaMoney; - case SqlDbType.NChar: - return MetaNChar; - case SqlDbType.NText: - return MetaNText; - case SqlDbType.NVarChar: - return MetaNVarChar; - case SqlDbType.Real: - return MetaReal; - case SqlDbType.UniqueIdentifier: - return MetaUniqueId; - case SqlDbType.SmallDateTime: - return MetaSmallDateTime; - case SqlDbType.SmallInt: - return MetaSmallInt; - case SqlDbType.SmallMoney: - return MetaSmallMoney; - case SqlDbType.Text: - return MetaText; - case SqlDbType.Timestamp: - return MetaTimestamp; - case SqlDbType.TinyInt: - return MetaTinyInt; - case SqlDbType.VarBinary: - return MetaVarBinary; - case SqlDbType.VarChar: - return MetaVarChar; - case SqlDbType.Variant: - return MetaVariant; - case (SqlDbType)TdsEnums.SmallVarBinary: - return MetaSmallVarBinary; - case SqlDbType.Xml: - return MetaXml; - case SqlDbType.Udt: - return MetaUdt; - case SqlDbType.Structured: - if (isMultiValued) - { - return MetaTable; - } - else - { - return MetaSUDT; - } - case SqlDbType.Date: - return MetaDate; - case SqlDbType.Time: - return MetaTime; - case SqlDbType.DateTime2: - return MetaDateTime2; - case SqlDbType.DateTimeOffset: - return MetaDateTimeOffset; - default: - throw SQL.InvalidSqlDbType(target); - } - } - - // - // map DbType to MetaType class - // - internal static MetaType GetMetaTypeFromDbType(DbType target) - { - // if we can't map it, we need to throw - switch (target) - { - case DbType.AnsiString: - return MetaVarChar; - case DbType.AnsiStringFixedLength: - return MetaChar; - case DbType.Binary: - return MetaVarBinary; - case DbType.Byte: - return MetaTinyInt; - case DbType.Boolean: - return MetaBit; - case DbType.Currency: - return MetaMoney; - case DbType.Date: - return MetaDate; - case DbType.DateTime: - return MetaDateTime; - case DbType.Decimal: - return MetaDecimal; - case DbType.Double: - return MetaFloat; - case DbType.Guid: - return MetaUniqueId; - case DbType.Int16: - return MetaSmallInt; - case DbType.Int32: - return MetaInt; - case DbType.Int64: - return MetaBigInt; - case DbType.Object: - return MetaVariant; - case DbType.Single: - return MetaReal; - case DbType.String: - return MetaNVarChar; - case DbType.StringFixedLength: - return MetaNChar; - case DbType.Time: - return MetaTime; - case DbType.Xml: - return MetaXml; - case DbType.DateTime2: - return MetaDateTime2; - case DbType.DateTimeOffset: - return MetaDateTimeOffset; - case DbType.SByte: // unsupported - case DbType.UInt16: - case DbType.UInt32: - case DbType.UInt64: - case DbType.VarNumeric: - default: - throw ADP.DbTypeNotSupported(target, typeof(SqlDbType)); // no direct mapping, error out - } - } - - internal static MetaType GetMaxMetaTypeFromMetaType(MetaType mt) - { - // if we can't map it, we need to throw - switch (mt.SqlDbType) - { - case SqlDbType.VarBinary: - case SqlDbType.Binary: - return MetaMaxVarBinary; - case SqlDbType.VarChar: - case SqlDbType.Char: - return MetaMaxVarChar; - case SqlDbType.NVarChar: - case SqlDbType.NChar: - return MetaMaxNVarChar; - case SqlDbType.Udt: - // TODO: we should probably verify we are hitting WinFS, otherwise this is invalid - return MetaMaxUdt; - default: - return mt; - } - } - - // - // map COM+ Type to MetaType class - // - static internal MetaType GetMetaTypeFromType(Type dataType) - { - return GetMetaTypeFromValue(dataType, null, false, true); - } - static internal MetaType GetMetaTypeFromValue(object value, bool streamAllowed = true) - { - return GetMetaTypeFromValue(value.GetType(), value, true, streamAllowed); - } - - static private MetaType GetMetaTypeFromValue(Type dataType, object value, bool inferLen, bool streamAllowed) - { - switch (Type.GetTypeCode(dataType)) - { - case TypeCode.Empty: - throw ADP.InvalidDataType(TypeCode.Empty); - case TypeCode.Object: - if (dataType == typeof(System.Byte[])) - { - // mdac 90455 must not default to image if inferLen is false ... - // - if (!inferLen || ((byte[])value).Length <= TdsEnums.TYPE_SIZE_LIMIT) - { - return MetaVarBinary; - } - else - { - return MetaImage; - } - } - else if (dataType == typeof(System.Guid)) - { - return MetaUniqueId; - } - else if (dataType == typeof(System.Object)) - { - return MetaVariant; - } // check sql types now - else if (dataType == typeof(SqlBinary)) - return MetaVarBinary; - else if (dataType == typeof(SqlBoolean)) - return MetaBit; - else if (dataType == typeof(SqlByte)) - return MetaTinyInt; - else if (dataType == typeof(SqlBytes)) - return MetaVarBinary; - else if (dataType == typeof(SqlChars)) - return MetaNVarChar; // MDAC 87587 - else if (dataType == typeof(SqlDateTime)) - return MetaDateTime; - else if (dataType == typeof(SqlDouble)) - return MetaFloat; - else if (dataType == typeof(SqlGuid)) - return MetaUniqueId; - else if (dataType == typeof(SqlInt16)) - return MetaSmallInt; - else if (dataType == typeof(SqlInt32)) - return MetaInt; - else if (dataType == typeof(SqlInt64)) - return MetaBigInt; - else if (dataType == typeof(SqlMoney)) - return MetaMoney; - else if (dataType == typeof(SqlDecimal)) - return MetaDecimal; - else if (dataType == typeof(SqlSingle)) - return MetaReal; - else if (dataType == typeof(SqlXml)) - return MetaXml; - else if (dataType == typeof(SqlString)) - { - return ((inferLen && !((SqlString)value).IsNull) ? PromoteStringType(((SqlString)value).Value) : MetaNVarChar); // MDAC 87587 - } - else if (dataType == typeof(IEnumerable) || dataType == typeof(DataTable)) - { - return MetaTable; - } - else if (dataType == typeof(TimeSpan)) - { - return MetaTime; - } - else if (dataType == typeof(DateTimeOffset)) - { - return MetaDateTimeOffset; - } - else - { - // UDT ? - SqlUdtInfo attribs = SqlUdtInfo.TryGetFromType(dataType); - if (attribs != null) - { - return MetaUdt; - } - if (streamAllowed) - { - // Derived from Stream ? - if (typeof(Stream).IsAssignableFrom(dataType)) - { - return MetaVarBinary; - } - // Derived from TextReader ? - if (typeof(TextReader).IsAssignableFrom(dataType)) - { - return MetaNVarChar; - } - // Derived from XmlReader ? - if (typeof(System.Xml.XmlReader).IsAssignableFrom(dataType)) - { - return MetaXml; - } - } - } - throw ADP.UnknownDataType(dataType); - - case TypeCode.DBNull: - throw ADP.InvalidDataType(TypeCode.DBNull); - case TypeCode.Boolean: - return MetaBit; - case TypeCode.Char: - throw ADP.InvalidDataType(TypeCode.Char); - case TypeCode.SByte: - throw ADP.InvalidDataType(TypeCode.SByte); - case TypeCode.Byte: - return MetaTinyInt; - case TypeCode.Int16: - return MetaSmallInt; - case TypeCode.UInt16: - throw ADP.InvalidDataType(TypeCode.UInt16); - case TypeCode.Int32: - return MetaInt; - case TypeCode.UInt32: - throw ADP.InvalidDataType(TypeCode.UInt32); - case TypeCode.Int64: - return MetaBigInt; - case TypeCode.UInt64: - throw ADP.InvalidDataType(TypeCode.UInt64); - case TypeCode.Single: - return MetaReal; - case TypeCode.Double: - return MetaFloat; - case TypeCode.Decimal: - return MetaDecimal; - case TypeCode.DateTime: - return MetaDateTime; - case TypeCode.String: - return (inferLen ? PromoteStringType((string)value) : MetaNVarChar); - default: - throw ADP.UnknownDataTypeCode(dataType, Type.GetTypeCode(dataType)); - } - } - - internal static object GetNullSqlValue(Type sqlType) - { - if (sqlType == typeof(SqlSingle)) - return SqlSingle.Null; - else if (sqlType == typeof(SqlString)) - return SqlString.Null; - else if (sqlType == typeof(SqlDouble)) - return SqlDouble.Null; - else if (sqlType == typeof(SqlBinary)) - return SqlBinary.Null; - else if (sqlType == typeof(SqlGuid)) - return SqlGuid.Null; - else if (sqlType == typeof(SqlBoolean)) - return SqlBoolean.Null; - else if (sqlType == typeof(SqlByte)) - return SqlByte.Null; - else if (sqlType == typeof(SqlInt16)) - return SqlInt16.Null; - else if (sqlType == typeof(SqlInt32)) - return SqlInt32.Null; - else if (sqlType == typeof(SqlInt64)) - return SqlInt64.Null; - else if (sqlType == typeof(SqlDecimal)) - return SqlDecimal.Null; - else if (sqlType == typeof(SqlDateTime)) - return SqlDateTime.Null; - else if (sqlType == typeof(SqlMoney)) - return SqlMoney.Null; - else if (sqlType == typeof(SqlXml)) - return SqlXml.Null; - else if (sqlType == typeof(object)) - return DBNull.Value; - else if (sqlType == typeof(IEnumerable)) - return DBNull.Value; - else if (sqlType == typeof(DataTable)) - return DBNull.Value; - else if (sqlType == typeof(DateTime)) - return DBNull.Value; - else if (sqlType == typeof(TimeSpan)) - return DBNull.Value; - else if (sqlType == typeof(DateTimeOffset)) - return DBNull.Value; - else - { - Debug.Assert(false, "Unknown SqlType!"); - return DBNull.Value; - } - } - - internal static MetaType PromoteStringType(string s) - { - int len = s.Length; - - if ((len << 1) > TdsEnums.TYPE_SIZE_LIMIT) - { - return MetaVarChar; // try as var char since we can send a 8K characters - } - return MetaNVarChar; // send 4k chars, but send as unicode - } - - internal static object GetComValueFromSqlVariant(object sqlVal) - { - object comVal = null; - - if (ADP.IsNull(sqlVal)) - return comVal; - - if (sqlVal is SqlSingle) - comVal = ((SqlSingle)sqlVal).Value; - else if (sqlVal is SqlString) - comVal = ((SqlString)sqlVal).Value; - else if (sqlVal is SqlDouble) - comVal = ((SqlDouble)sqlVal).Value; - else if (sqlVal is SqlBinary) - comVal = ((SqlBinary)sqlVal).Value; - else if (sqlVal is SqlGuid) - comVal = ((SqlGuid)sqlVal).Value; - else if (sqlVal is SqlBoolean) - comVal = ((SqlBoolean)sqlVal).Value; - else if (sqlVal is SqlByte) - comVal = ((SqlByte)sqlVal).Value; - else if (sqlVal is SqlInt16) - comVal = ((SqlInt16)sqlVal).Value; - else if (sqlVal is SqlInt32) - comVal = ((SqlInt32)sqlVal).Value; - else if (sqlVal is SqlInt64) - comVal = ((SqlInt64)sqlVal).Value; - else if (sqlVal is SqlDecimal) - comVal = ((SqlDecimal)sqlVal).Value; - else if (sqlVal is SqlDateTime) - comVal = ((SqlDateTime)sqlVal).Value; - else if (sqlVal is SqlMoney) - comVal = ((SqlMoney)sqlVal).Value; - else if (sqlVal is SqlXml) - comVal = ((SqlXml)sqlVal).Value; - else - { - AssertIsUserDefinedTypeInstance(sqlVal, "unknown SqlType class stored in sqlVal"); - } - - - return comVal; - } - - /// - /// Assert that the supplied object is an instance of a SQL User-Defined Type (UDT). - /// - /// Object instance to be tested. - /// - /// - /// This method is only compiled with debug builds, and it a helper method for the GetComValueFromSqlVariant method defined in this class. - /// - /// The presence of the SqlUserDefinedTypeAttribute on the object's type - /// is used to determine if the object is a UDT instance (if present it is a UDT, else it is not). - /// - /// - /// If sqlValue is null. Callers must ensure the object is non-null. - /// - [Conditional("DEBUG")] - private static void AssertIsUserDefinedTypeInstance(object sqlValue, string failedAssertMessage) - { - Type type = sqlValue.GetType(); - Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute[] attributes = (Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute[])type.GetCustomAttributes(typeof(Microsoft.SqlServer.Server.SqlUserDefinedTypeAttribute), true); - - Debug.Assert(attributes.Length > 0, failedAssertMessage); - } - - // devnote: This method should not be used with SqlDbType.Date and SqlDbType.DateTime2. - // With these types the values should be used directly as CLR types instead of being converted to a SqlValue - internal static object GetSqlValueFromComVariant(object comVal) - { - object sqlVal = null; - if ((null != comVal) && (DBNull.Value != comVal)) - { - if (comVal is float) - sqlVal = new SqlSingle((float)comVal); - else if (comVal is string) - sqlVal = new SqlString((string)comVal); - else if (comVal is double) - sqlVal = new SqlDouble((double)comVal); - else if (comVal is System.Byte[]) - sqlVal = new SqlBinary((byte[])comVal); - else if (comVal is System.Char) - sqlVal = new SqlString(((char)comVal).ToString()); - else if (comVal is System.Char[]) - sqlVal = new SqlChars((System.Char[])comVal); - else if (comVal is System.Guid) - sqlVal = new SqlGuid((Guid)comVal); - else if (comVal is bool) - sqlVal = new SqlBoolean((bool)comVal); - else if (comVal is byte) - sqlVal = new SqlByte((byte)comVal); - else if (comVal is Int16) - sqlVal = new SqlInt16((Int16)comVal); - else if (comVal is Int32) - sqlVal = new SqlInt32((Int32)comVal); - else if (comVal is Int64) - sqlVal = new SqlInt64((Int64)comVal); - else if (comVal is Decimal) - sqlVal = new SqlDecimal((Decimal)comVal); - else if (comVal is DateTime) - { - // devnote: Do not use with SqlDbType.Date and SqlDbType.DateTime2. See comment at top of method. - sqlVal = new SqlDateTime((DateTime)comVal); - } - else if (comVal is XmlReader) - sqlVal = new SqlXml((XmlReader)comVal); - else if (comVal is TimeSpan || comVal is DateTimeOffset) - sqlVal = comVal; -#if DEBUG - else - Debug.Assert(false, "unknown SqlType class stored in sqlVal"); -#endif - } - return sqlVal; - } - - internal static SqlDbType GetSqlDbTypeFromOleDbType(short dbType, string typeName) - { - SqlDbType sqlType = SqlDbType.Variant; - switch ((OleDbType)dbType) - { - case OleDbType.BigInt: - sqlType = SqlDbType.BigInt; - break; - case OleDbType.Boolean: - sqlType = SqlDbType.Bit; - break; - case OleDbType.Char: - case OleDbType.VarChar: - // these guys are ambiguous - server sends over DBTYPE_STR in both cases - sqlType = (typeName == MetaTypeName.CHAR) ? SqlDbType.Char : SqlDbType.VarChar; - break; - case OleDbType.Currency: - sqlType = (typeName == MetaTypeName.SMALLMONEY) ? SqlDbType.SmallMoney : SqlDbType.Money; - break; - case OleDbType.Date: - case OleDbType.DBTimeStamp: - case OleDbType.Filetime: - switch (typeName) - { - case MetaTypeName.SMALLDATETIME: - sqlType = SqlDbType.SmallDateTime; - break; - case MetaTypeName.DATETIME2: - sqlType = SqlDbType.DateTime2; - break; - default: - sqlType = SqlDbType.DateTime; - break; - } - break; - case OleDbType.Decimal: - case OleDbType.Numeric: - sqlType = SqlDbType.Decimal; - break; - case OleDbType.Double: - sqlType = SqlDbType.Float; - break; - case OleDbType.Guid: - sqlType = SqlDbType.UniqueIdentifier; - break; - case OleDbType.Integer: - sqlType = SqlDbType.Int; - break; - case OleDbType.LongVarBinary: - sqlType = SqlDbType.Image; - break; - case OleDbType.LongVarChar: - sqlType = SqlDbType.Text; - break; - case OleDbType.LongVarWChar: - sqlType = SqlDbType.NText; - break; - case OleDbType.Single: - sqlType = SqlDbType.Real; - break; - case OleDbType.SmallInt: - case OleDbType.UnsignedSmallInt: - sqlType = SqlDbType.SmallInt; - break; - case OleDbType.TinyInt: - case OleDbType.UnsignedTinyInt: - sqlType = SqlDbType.TinyInt; - break; - case OleDbType.VarBinary: - case OleDbType.Binary: - sqlType = (typeName == MetaTypeName.BINARY) ? SqlDbType.Binary : SqlDbType.VarBinary; - break; - case OleDbType.Variant: - sqlType = SqlDbType.Variant; - break; - case OleDbType.VarWChar: - case OleDbType.WChar: - case OleDbType.BSTR: - // these guys are ambiguous - server sends over DBTYPE_WSTR in both cases - // BSTR is always assumed to be NVARCHAR - sqlType = (typeName == MetaTypeName.NCHAR) ? SqlDbType.NChar : SqlDbType.NVarChar; - break; - case OleDbType.DBDate: // Date - sqlType = SqlDbType.Date; - break; - case (OleDbType)132: // Udt - sqlType = SqlDbType.Udt; - break; - case (OleDbType)141: // Xml - sqlType = SqlDbType.Xml; - break; - case (OleDbType)145: // Time - sqlType = SqlDbType.Time; - break; - case (OleDbType)146: // DateTimeOffset - sqlType = SqlDbType.DateTimeOffset; - break; - // TODO: Handle Structured types for derive parameters - default: - break; // no direct mapping, just use SqlDbType.Variant; - } - - return sqlType; - } - - internal static MetaType GetSqlDataType(int tdsType, UInt32 userType, int length) - { - switch (tdsType) - { - case TdsEnums.SQLMONEYN: - return ((4 == length) ? MetaSmallMoney : MetaMoney); - case TdsEnums.SQLDATETIMN: - return ((4 == length) ? MetaSmallDateTime : MetaDateTime); - case TdsEnums.SQLINTN: - return ((4 <= length) ? ((4 == length) ? MetaInt : MetaBigInt) : ((2 == length) ? MetaSmallInt : MetaTinyInt)); - case TdsEnums.SQLFLTN: - return ((4 == length) ? MetaReal : MetaFloat); - case TdsEnums.SQLTEXT: - return MetaText; - case TdsEnums.SQLVARBINARY: - return MetaSmallVarBinary; - case TdsEnums.SQLBIGVARBINARY: - return MetaVarBinary; - - case TdsEnums.SQLVARCHAR: //goto TdsEnums.SQLBIGVARCHAR; - case TdsEnums.SQLBIGVARCHAR: - return MetaVarChar; - - case TdsEnums.SQLBINARY: //goto TdsEnums.SQLBIGBINARY; - case TdsEnums.SQLBIGBINARY: - return ((TdsEnums.SQLTIMESTAMP == userType) ? MetaTimestamp : MetaBinary); - - case TdsEnums.SQLIMAGE: - return MetaImage; - - case TdsEnums.SQLCHAR: //goto TdsEnums.SQLBIGCHAR; - case TdsEnums.SQLBIGCHAR: - return MetaChar; - - case TdsEnums.SQLINT1: - return MetaTinyInt; - - case TdsEnums.SQLBIT: //goto TdsEnums.SQLBITN; - case TdsEnums.SQLBITN: - return MetaBit; - - case TdsEnums.SQLINT2: - return MetaSmallInt; - case TdsEnums.SQLINT4: - return MetaInt; - case TdsEnums.SQLINT8: - return MetaBigInt; - case TdsEnums.SQLMONEY: - return MetaMoney; - case TdsEnums.SQLDATETIME: - return MetaDateTime; - case TdsEnums.SQLFLT8: - return MetaFloat; - case TdsEnums.SQLFLT4: - return MetaReal; - case TdsEnums.SQLMONEY4: - return MetaSmallMoney; - case TdsEnums.SQLDATETIM4: - return MetaSmallDateTime; - - case TdsEnums.SQLDECIMALN: //goto TdsEnums.SQLNUMERICN; - case TdsEnums.SQLNUMERICN: - return MetaDecimal; - - case TdsEnums.SQLUNIQUEID: - return MetaUniqueId; - case TdsEnums.SQLNCHAR: - return MetaNChar; - case TdsEnums.SQLNVARCHAR: - return MetaNVarChar; - case TdsEnums.SQLNTEXT: - return MetaNText; - case TdsEnums.SQLVARIANT: - return MetaVariant; - case TdsEnums.SQLUDT: - return MetaUdt; - case TdsEnums.SQLXMLTYPE: - return MetaXml; - case TdsEnums.SQLTABLE: - return MetaTable; - case TdsEnums.SQLDATE: - return MetaDate; - case TdsEnums.SQLTIME: - return MetaTime; - case TdsEnums.SQLDATETIME2: - return MetaDateTime2; - case TdsEnums.SQLDATETIMEOFFSET: - return MetaDateTimeOffset; - - case TdsEnums.SQLVOID: - default: - Debug.Assert(false, "Unknown type " + tdsType.ToString(CultureInfo.InvariantCulture)); - throw SQL.InvalidSqlDbType((SqlDbType)tdsType); - }// case - } - - internal static MetaType GetDefaultMetaType() - { - return MetaNVarChar; - } - - // Converts an XmlReader into String - internal static String GetStringFromXml(XmlReader xmlreader) - { - SqlXml sxml = new SqlXml(xmlreader); - return sxml.Value; - } - - private static readonly MetaType MetaBigInt = new MetaType - (19, 255, 8, true, false, false, TdsEnums.SQLINT8, TdsEnums.SQLINTN, MetaTypeName.BIGINT, typeof(System.Int64), typeof(SqlInt64), SqlDbType.BigInt, DbType.Int64, 0); - - private static readonly MetaType MetaFloat = new MetaType - (15, 255, 8, true, false, false, TdsEnums.SQLFLT8, TdsEnums.SQLFLTN, MetaTypeName.FLOAT, typeof(System.Double), typeof(SqlDouble), SqlDbType.Float, DbType.Double, 0); - - private static readonly MetaType MetaReal = new MetaType - (7, 255, 4, true, false, false, TdsEnums.SQLFLT4, TdsEnums.SQLFLTN, MetaTypeName.REAL, typeof(System.Single), typeof(SqlSingle), SqlDbType.Real, DbType.Single, 0); - - // MetaBinary has two bytes of properties for binary and varbinary - // 2 byte maxlen - private static readonly MetaType MetaBinary = new MetaType - (255, 255, -1, false, false, false, TdsEnums.SQLBIGBINARY, TdsEnums.SQLBIGBINARY, MetaTypeName.BINARY, typeof(System.Byte[]), typeof(SqlBinary), SqlDbType.Binary, DbType.Binary, 2); - - // syntatic sugar for the user...timestamps are 8-byte fixed length binary columns - private static readonly MetaType MetaTimestamp = new MetaType - (255, 255, -1, false, false, false, TdsEnums.SQLBIGBINARY, TdsEnums.SQLBIGBINARY, MetaTypeName.TIMESTAMP, typeof(System.Byte[]), typeof(SqlBinary), SqlDbType.Timestamp, DbType.Binary, 2); - - internal static readonly MetaType MetaVarBinary = new MetaType - (255, 255, -1, false, false, false, TdsEnums.SQLBIGVARBINARY, TdsEnums.SQLBIGVARBINARY, MetaTypeName.VARBINARY, typeof(System.Byte[]), typeof(SqlBinary), SqlDbType.VarBinary, DbType.Binary, 2); - - internal static readonly MetaType MetaMaxVarBinary = new MetaType - (255, 255, -1, false, true, true, TdsEnums.SQLBIGVARBINARY, TdsEnums.SQLBIGVARBINARY, MetaTypeName.VARBINARY, typeof(System.Byte[]), typeof(SqlBinary), SqlDbType.VarBinary, DbType.Binary, 2); - - // HACK!!! We have an internal type for smallvarbinarys stored on TdsEnums. We - // store on TdsEnums instead of SqlDbType because we do not want to expose - // this type to the user! - private static readonly MetaType MetaSmallVarBinary = new MetaType - (255, 255, -1, false, false, false, TdsEnums.SQLVARBINARY, TdsEnums.SQLBIGBINARY, "", typeof(System.Byte[]), typeof(SqlBinary), TdsEnums.SmallVarBinary, DbType.Binary, 2); - - internal static readonly MetaType MetaImage = new MetaType - (255, 255, -1, false, true, false, TdsEnums.SQLIMAGE, TdsEnums.SQLIMAGE, MetaTypeName.IMAGE, typeof(System.Byte[]), typeof(SqlBinary), SqlDbType.Image, DbType.Binary, 0); - - private static readonly MetaType MetaBit = new MetaType - (255, 255, 1, true, false, false, TdsEnums.SQLBIT, TdsEnums.SQLBITN, MetaTypeName.BIT, typeof(System.Boolean), typeof(SqlBoolean), SqlDbType.Bit, DbType.Boolean, 0); - - private static readonly MetaType MetaTinyInt = new MetaType - (3, 255, 1, true, false, false, TdsEnums.SQLINT1, TdsEnums.SQLINTN, MetaTypeName.TINYINT, typeof(System.Byte), typeof(SqlByte), SqlDbType.TinyInt, DbType.Byte, 0); - - private static readonly MetaType MetaSmallInt = new MetaType - (5, 255, 2, true, false, false, TdsEnums.SQLINT2, TdsEnums.SQLINTN, MetaTypeName.SMALLINT, typeof(System.Int16), typeof(SqlInt16), SqlDbType.SmallInt, DbType.Int16, 0); - - private static readonly MetaType MetaInt = new MetaType - (10, 255, 4, true, false, false, TdsEnums.SQLINT4, TdsEnums.SQLINTN, MetaTypeName.INT, typeof(System.Int32), typeof(SqlInt32), SqlDbType.Int, DbType.Int32, 0); - - // MetaVariant has seven bytes of properties for MetaChar and MetaVarChar - // 5 byte tds collation - // 2 byte maxlen - private static readonly MetaType MetaChar = new MetaType - (255, 255, -1, false, false, false, TdsEnums.SQLBIGCHAR, TdsEnums.SQLBIGCHAR, MetaTypeName.CHAR, typeof(System.String), typeof(SqlString), SqlDbType.Char, DbType.AnsiStringFixedLength, 7); - - private static readonly MetaType MetaVarChar = new MetaType - (255, 255, -1, false, false, false, TdsEnums.SQLBIGVARCHAR, TdsEnums.SQLBIGVARCHAR, MetaTypeName.VARCHAR, typeof(System.String), typeof(SqlString), SqlDbType.VarChar, DbType.AnsiString, 7); - - internal static readonly MetaType MetaMaxVarChar = new MetaType - (255, 255, -1, false, true, true, TdsEnums.SQLBIGVARCHAR, TdsEnums.SQLBIGVARCHAR, MetaTypeName.VARCHAR, typeof(System.String), typeof(SqlString), SqlDbType.VarChar, DbType.AnsiString, 7); - - internal static readonly MetaType MetaText = new MetaType - (255, 255, -1, false, true, false, TdsEnums.SQLTEXT, TdsEnums.SQLTEXT, MetaTypeName.TEXT, typeof(System.String), typeof(SqlString), SqlDbType.Text, DbType.AnsiString, 0); - - // MetaVariant has seven bytes of properties for MetaNChar and MetaNVarChar - // 5 byte tds collation - // 2 byte maxlen - private static readonly MetaType MetaNChar = new MetaType - (255, 255, -1, false, false, false, TdsEnums.SQLNCHAR, TdsEnums.SQLNCHAR, MetaTypeName.NCHAR, typeof(System.String), typeof(SqlString), SqlDbType.NChar, DbType.StringFixedLength, 7); - - internal static readonly MetaType MetaNVarChar = new MetaType - (255, 255, -1, false, false, false, TdsEnums.SQLNVARCHAR, TdsEnums.SQLNVARCHAR, MetaTypeName.NVARCHAR, typeof(System.String), typeof(SqlString), SqlDbType.NVarChar, DbType.String, 7); - - internal static readonly MetaType MetaMaxNVarChar = new MetaType - (255, 255, -1, false, true, true, TdsEnums.SQLNVARCHAR, TdsEnums.SQLNVARCHAR, MetaTypeName.NVARCHAR, typeof(System.String), typeof(SqlString), SqlDbType.NVarChar, DbType.String, 7); - - internal static readonly MetaType MetaNText = new MetaType - (255, 255, -1, false, true, false, TdsEnums.SQLNTEXT, TdsEnums.SQLNTEXT, MetaTypeName.NTEXT, typeof(System.String), typeof(SqlString), SqlDbType.NText, DbType.String, 7); - - // MetaVariant has two bytes of properties for numeric/decimal types - // 1 byte precision - // 1 byte scale - internal static readonly MetaType MetaDecimal = new MetaType - (38, 4, 17, true, false, false, TdsEnums.SQLNUMERICN, TdsEnums.SQLNUMERICN, MetaTypeName.DECIMAL, typeof(System.Decimal), typeof(SqlDecimal), SqlDbType.Decimal, DbType.Decimal, 2); - - internal static readonly MetaType MetaXml = new MetaType - (255, 255, -1, false, true, true, TdsEnums.SQLXMLTYPE, TdsEnums.SQLXMLTYPE, MetaTypeName.XML, typeof(System.String), typeof(SqlXml), SqlDbType.Xml, DbType.Xml, 0); - - private static readonly MetaType MetaDateTime = new MetaType - (23, 3, 8, true, false, false, TdsEnums.SQLDATETIME, TdsEnums.SQLDATETIMN, MetaTypeName.DATETIME, typeof(System.DateTime), typeof(SqlDateTime), SqlDbType.DateTime, DbType.DateTime, 0); - - private static readonly MetaType MetaSmallDateTime = new MetaType - (16, 0, 4, true, false, false, TdsEnums.SQLDATETIM4, TdsEnums.SQLDATETIMN, MetaTypeName.SMALLDATETIME, typeof(System.DateTime), typeof(SqlDateTime), SqlDbType.SmallDateTime, DbType.DateTime, 0); - - private static readonly MetaType MetaMoney = new MetaType - (19, 255, 8, true, false, false, TdsEnums.SQLMONEY, TdsEnums.SQLMONEYN, MetaTypeName.MONEY, typeof(System.Decimal), typeof(SqlMoney), SqlDbType.Money, DbType.Currency, 0); - - private static readonly MetaType MetaSmallMoney = new MetaType - (10, 255, 4, true, false, false, TdsEnums.SQLMONEY4, TdsEnums.SQLMONEYN, MetaTypeName.SMALLMONEY, typeof(System.Decimal), typeof(SqlMoney), SqlDbType.SmallMoney, DbType.Currency, 0); - - private static readonly MetaType MetaUniqueId = new MetaType - (255, 255, 16, true, false, false, TdsEnums.SQLUNIQUEID, TdsEnums.SQLUNIQUEID, MetaTypeName.ROWGUID, typeof(System.Guid), typeof(SqlGuid), SqlDbType.UniqueIdentifier, DbType.Guid, 0); - - private static readonly MetaType MetaVariant = new MetaType - (255, 255, -1, true, false, false, TdsEnums.SQLVARIANT, TdsEnums.SQLVARIANT, MetaTypeName.VARIANT, typeof(System.Object), typeof(System.Object), SqlDbType.Variant, DbType.Object, 0); - - internal static readonly MetaType MetaUdt = new MetaType - (255, 255, -1, false, false, true, TdsEnums.SQLUDT, TdsEnums.SQLUDT, MetaTypeName.UDT, typeof(System.Object), typeof(System.Object), SqlDbType.Udt, DbType.Object, 0); - - private static readonly MetaType MetaMaxUdt = new MetaType - (255, 255, -1, false, true, true, TdsEnums.SQLUDT, TdsEnums.SQLUDT, MetaTypeName.UDT, typeof(System.Object), typeof(System.Object), SqlDbType.Udt, DbType.Object, 0); - - private static readonly MetaType MetaTable = new MetaType - (255, 255, -1, false, false, false, TdsEnums.SQLTABLE, TdsEnums.SQLTABLE, MetaTypeName.TABLE, typeof(IEnumerable), typeof(IEnumerable), SqlDbType.Structured, DbType.Object, 0); - - // TODO: MetaSUDT is required for parameter.Add("", SqlDbType.Structured) to work. We'll need to update it - // with real values when implementing structured UDTs. - private static readonly MetaType MetaSUDT = new MetaType - (255, 255, -1, false, false, false, TdsEnums.SQLVOID, TdsEnums.SQLVOID, "", typeof(SqlDataRecord), typeof(SqlDataRecord), SqlDbType.Structured, DbType.Object, 0); - - private static readonly MetaType MetaDate = new MetaType - (255, 255, 3, true, false, false, TdsEnums.SQLDATE, TdsEnums.SQLDATE, MetaTypeName.DATE, typeof(System.DateTime), typeof(System.DateTime), SqlDbType.Date, DbType.Date, 0); - - internal static readonly MetaType MetaTime = new MetaType - (255, 7, -1, false, false, false, TdsEnums.SQLTIME, TdsEnums.SQLTIME, MetaTypeName.TIME, typeof(System.TimeSpan), typeof(System.TimeSpan), SqlDbType.Time, DbType.Time, 1); - - private static readonly MetaType MetaDateTime2 = new MetaType - (255, 7, -1, false, false, false, TdsEnums.SQLDATETIME2, TdsEnums.SQLDATETIME2, MetaTypeName.DATETIME2, typeof(System.DateTime), typeof(System.DateTime), SqlDbType.DateTime2, DbType.DateTime2, 1); - - internal static readonly MetaType MetaDateTimeOffset = new MetaType - (255, 7, -1, false, false, false, TdsEnums.SQLDATETIMEOFFSET, TdsEnums.SQLDATETIMEOFFSET, MetaTypeName.DATETIMEOFFSET, typeof(System.DateTimeOffset), typeof(System.DateTimeOffset), SqlDbType.DateTimeOffset, DbType.DateTimeOffset, 1); - - public static TdsDateTime FromDateTime(DateTime dateTime, byte cb) - { - SqlDateTime sqlDateTime; - TdsDateTime tdsDateTime = new TdsDateTime(); - - Debug.Assert(cb == 8 || cb == 4, "Invalid date time size!"); - - if (cb == 8) - { - sqlDateTime = new SqlDateTime(dateTime); - tdsDateTime.time = sqlDateTime.TimeTicks; - } - else - { - // note that smalldatetime is days&minutes. - // Adding 30 seconds ensures proper roundup if the seconds are >= 30 - // The AddSeconds function handles eventual carryover - sqlDateTime = new SqlDateTime(dateTime.AddSeconds(30)); - tdsDateTime.time = sqlDateTime.TimeTicks / SqlDateTime.SQLTicksPerMinute; - } - tdsDateTime.days = sqlDateTime.DayTicks; - return tdsDateTime; - } - - - public static DateTime ToDateTime(int sqlDays, int sqlTime, int length) - { - if (length == 4) - { - return new SqlDateTime(sqlDays, sqlTime * SqlDateTime.SQLTicksPerMinute).Value; - } - else - { - Debug.Assert(length == 8, "invalid length for DateTime"); - return new SqlDateTime(sqlDays, sqlTime).Value; - } - } - - internal static int GetTimeSizeFromScale(byte scale) - { - // Disable the assert here since we do not properly handle wrong Scale value on the parameter, - // see VSTFDEVDIV 795578 for more details. - // But, this assert is still valid when we receive Time/DateTime2/DateTimeOffset scale from server over TDS, - // so it is moved to TdsParser.CommonProcessMetaData. - // For new scenarios, assert and/or validate the scale value before this call! - // Debug.Assert(0 <= scale && scale <= 7); - - if (scale <= 2) - return 3; - - if (scale <= 4) - return 4; - - return 5; - } - - // - // please leave string sorted alphabetically - // note that these names should only be used in the context of parameters. We always send over BIG* and nullable types for SQL Server - // - private static class MetaTypeName - { - public const string BIGINT = "bigint"; - public const string BINARY = "binary"; - public const string BIT = "bit"; - public const string CHAR = "char"; - public const string DATETIME = "datetime"; - public const string DECIMAL = "decimal"; - public const string FLOAT = "float"; - public const string IMAGE = "image"; - public const string INT = "int"; - public const string MONEY = "money"; - public const string NCHAR = "nchar"; - public const string NTEXT = "ntext"; - public const string NVARCHAR = "nvarchar"; - public const string REAL = "real"; - public const string ROWGUID = "uniqueidentifier"; - public const string SMALLDATETIME = "smalldatetime"; - public const string SMALLINT = "smallint"; - public const string SMALLMONEY = "smallmoney"; - public const string TEXT = "text"; - public const string TIMESTAMP = "timestamp"; - public const string TINYINT = "tinyint"; - public const string UDT = "udt"; - public const string VARBINARY = "varbinary"; - public const string VARCHAR = "varchar"; - public const string VARIANT = "sql_variant"; - public const string XML = "xml"; - public const string TABLE = "table"; - public const string DATE = "date"; - public const string TIME = "time"; - public const string DATETIME2 = "datetime2"; - public const string DATETIMEOFFSET = "datetimeoffset"; - } - } - - // - // note: it is the client's responsibility to know what size date time he is working with - // - internal struct TdsDateTime - { - public int days; // offset in days from 1/1/1900 - // private UInt32 time; // if smalldatetime, this is # of minutes since midnight - // otherwise: # of 1/300th of a second since midnight - public int time; // UNDONE, use UInt32 when available! (0716 compiler??) - } - -} - diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlErrorCollection.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlErrorCollection.cs deleted file mode 100644 index c49d345266..0000000000 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlErrorCollection.cs +++ /dev/null @@ -1,72 +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; -using System.ComponentModel; - -namespace Microsoft.Data.SqlClient -{ - /// - [Serializable, ListBindable(false)] - public sealed class SqlErrorCollection : ICollection - { - - private ArrayList errors = new ArrayList(); - - internal SqlErrorCollection() - { - } - - /// - public void CopyTo(Array array, int index) - { - this.errors.CopyTo(array, index); - } - - /// - public void CopyTo(SqlError[] array, int index) - { - this.errors.CopyTo(array, index); - } - - /// - public int Count - { - get { return this.errors.Count; } - } - - /// - object System.Collections.ICollection.SyncRoot - { // MDAC 68481 - get { return this; } - } - - /// - bool System.Collections.ICollection.IsSynchronized - { // MDAC 68481 - get { return false; } - } - - /// - public SqlError this[int index] - { - get - { - return (SqlError)this.errors[index]; - } - } - - /// - public IEnumerator GetEnumerator() - { - return errors.GetEnumerator(); - } - - internal void Add(SqlError error) - { - this.errors.Add(error); - } - } -} diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlException.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlException.cs deleted file mode 100644 index b4e0c7ea2c..0000000000 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlException.cs +++ /dev/null @@ -1,247 +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; -using System.ComponentModel; -using System.Diagnostics; -using System.Globalization; -using System.Runtime.Serialization; -using System.Text; -using Microsoft.Data.Common; - -namespace Microsoft.Data.SqlClient -{ - /// - [Serializable] - public sealed class SqlException : System.Data.Common.DbException - { - private const string OriginalClientConnectionIdKey = "OriginalClientConnectionId"; - private const string RoutingDestinationKey = "RoutingDestination"; - private const int SqlExceptionHResult = unchecked((int)0x80131904); - - private SqlErrorCollection _errors; - [System.Runtime.Serialization.OptionalFieldAttribute(VersionAdded = 4)] - private Guid _clientConnectionId = Guid.Empty; - - private SqlException(string message, SqlErrorCollection errorCollection, Exception innerException, Guid conId) : base(message, innerException) - { - HResult = SqlExceptionHResult; - _errors = errorCollection; - _clientConnectionId = conId; - } - - // runtime will call even if private... - private SqlException(SerializationInfo si, StreamingContext sc) : base(si, sc) - { - _errors = (SqlErrorCollection)si.GetValue("Errors", typeof(SqlErrorCollection)); - HResult = SqlExceptionHResult; - foreach (SerializationEntry siEntry in si) - { - if (nameof(ClientConnectionId) == siEntry.Name) - { - _clientConnectionId = (Guid)si.GetValue(nameof(ClientConnectionId), typeof(Guid)); - break; - } - } - } - - /// - override public void GetObjectData(SerializationInfo si, StreamingContext context) - { - base.GetObjectData(si, context); - si.AddValue("Errors", null); // Not specifying type to enable serialization of null value of non-serializable type - si.AddValue("ClientConnectionId", _clientConnectionId, typeof(object)); - - // Writing sqlerrors to base exception data table - for (int i = 0; i < Errors.Count; i++) - { - string key = "SqlError " + (i + 1); - if (Data.Contains(key)) - { - Data.Remove(key); - } - Data.Add(key, Errors[i].ToString()); - } - } - - /// - [ - DesignerSerializationVisibility(DesignerSerializationVisibility.Content) - ] - public SqlErrorCollection Errors - { - get - { - if (_errors == null) - { - _errors = new SqlErrorCollection(); - } - return _errors; - } - } - - /// - public Guid ClientConnectionId - { - get - { - return this._clientConnectionId; - } - } - - /*virtual protected*/ - private bool ShouldSerializeErrors() - { // MDAC 65548 - return ((null != _errors) && (0 < _errors.Count)); - } - - /// - public byte Class - { - get { return Errors.Count > 0 ? Errors[0].Class : default; } - } - - /// - public int LineNumber - { - get { return Errors.Count > 0 ? Errors[0].LineNumber : default; } - } - - /// - public int Number - { - get { return Errors.Count > 0 ? Errors[0].Number : default; } - } - - /// - public string Procedure - { - get { return Errors.Count > 0 ? Errors[0].Procedure : default; } - } - - /// - public string Server - { - get { return Errors.Count > 0 ? Errors[0].Server : default; } - } - - /// - public byte State - { - get { return Errors.Count > 0 ? Errors[0].State : default; } - } - - /// - override public string Source - { - get { return TdsEnums.SQL_PROVIDER_NAME; } - } - - /// - public override string ToString() - { - StringBuilder sb = new StringBuilder(base.ToString()); - sb.AppendLine(); - sb.AppendFormat(SQLMessage.ExClientConnectionId(), _clientConnectionId); - - // Append the error number, state and class if the server provided it - if (Errors.Count > 0 && Number != 0) - { - sb.AppendLine(); - sb.AppendFormat(SQLMessage.ExErrorNumberStateClass(), Number, State, Class); - } - - // If routed, include the original client connection id - if (Data.Contains(OriginalClientConnectionIdKey)) - { - sb.AppendLine(); - sb.AppendFormat(SQLMessage.ExOriginalClientConnectionId(), Data[OriginalClientConnectionIdKey]); - } - - // If routed, provide the routing destination - if (Data.Contains(RoutingDestinationKey)) - { - sb.AppendLine(); - sb.AppendFormat(SQLMessage.ExRoutingDestination(), Data[RoutingDestinationKey]); - } - - return sb.ToString(); - } - - internal static SqlException CreateException(SqlErrorCollection errorCollection, string serverVersion) - { - return CreateException(errorCollection, serverVersion, Guid.Empty); - } - - internal static SqlException CreateException(SqlErrorCollection errorCollection, string serverVersion, SqlInternalConnectionTds internalConnection, Exception innerException = null) - { - Guid connectionId = (internalConnection == null) ? Guid.Empty : internalConnection._clientConnectionId; - var exception = CreateException(errorCollection, serverVersion, connectionId, innerException); - - if (internalConnection != null) - { - if ((internalConnection.OriginalClientConnectionId != Guid.Empty) && (internalConnection.OriginalClientConnectionId != internalConnection.ClientConnectionId)) - { - exception.Data.Add(OriginalClientConnectionIdKey, internalConnection.OriginalClientConnectionId); - } - - if (!string.IsNullOrEmpty(internalConnection.RoutingDestination)) - { - exception.Data.Add(RoutingDestinationKey, internalConnection.RoutingDestination); - } - } - - return exception; - } - - internal static SqlException CreateException(SqlErrorCollection errorCollection, string serverVersion, Guid conId, Exception innerException = null) - { - Debug.Assert(null != errorCollection && errorCollection.Count > 0, "no errorCollection?"); - - StringBuilder message = new StringBuilder(); - for (int i = 0; i < errorCollection.Count; i++) - { - if (i > 0) - { - message.Append(Environment.NewLine); - } - message.Append(errorCollection[i].Message); - } - - if (innerException == null && errorCollection[0].Win32ErrorCode != 0 && errorCollection[0].Win32ErrorCode != -1) - { - innerException = new Win32Exception(errorCollection[0].Win32ErrorCode); - } - - SqlException exception = new SqlException(message.ToString(), errorCollection, innerException, conId); - - exception.Data.Add("HelpLink.ProdName", "Microsoft SQL Server"); - - if (!string.IsNullOrEmpty(serverVersion)) - { - exception.Data.Add("HelpLink.ProdVer", serverVersion); - } - exception.Data.Add("HelpLink.EvtSrc", "MSSQLServer"); - exception.Data.Add("HelpLink.EvtID", errorCollection[0].Number.ToString(CultureInfo.InvariantCulture)); - exception.Data.Add("HelpLink.BaseHelpUrl", "http://go.microsoft.com/fwlink"); - exception.Data.Add("HelpLink.LinkId", "20476"); - - return exception; - } - - internal SqlException InternalClone() - { - SqlException exception = new SqlException(Message, _errors, InnerException, _clientConnectionId); - if (this.Data != null) - foreach (DictionaryEntry entry in this.Data) - exception.Data.Add(entry.Key, entry.Value); - exception._doNotReconnect = this._doNotReconnect; - return exception; - } - - // Do not serialize this field! It is used to indicate that no reconnection attempts are required - internal bool _doNotReconnect = false; - } -} diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnection.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnection.cs index bb719f3f20..be0456685e 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnection.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnection.cs @@ -708,17 +708,6 @@ internal SqlDataReader FindLiveReader(SqlCommand command) return reader; } - internal SqlCommand FindLiveCommand(TdsParserStateObject stateObj) - { - SqlCommand command = null; - SqlReferenceCollection referenceCollection = (SqlReferenceCollection)ReferenceCollection; - if (null != referenceCollection) - { - command = referenceCollection.FindLiveCommand(stateObj); - } - return command; - } - static internal TdsParser GetBestEffortCleanupTarget(SqlConnection connection) { if (null != connection) diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs index c6844a0568..623ce80d93 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlInternalConnectionTds.cs @@ -1966,7 +1966,7 @@ private void LoginNoFailover(ServerInfo serverInfo, string newPassword, SecureSt // We must wait for CompleteLogin to finish for to have the // env change from the server to know its designated failover // partner; save this information in _currentFailoverPartner. - PoolGroupProviderInfo.FailoverCheck(this, false, connectionOptions, ServerProvidedFailOverPartner); + PoolGroupProviderInfo.FailoverCheck(false, connectionOptions, ServerProvidedFailOverPartner); } CurrentDataSource = originalServerInfo.UserServerName; } @@ -2235,7 +2235,7 @@ TimeoutTimer timeout // We must wait for CompleteLogin to finish for to have the // env change from the server to know its designated failover // partner; save this information in _currentFailoverPartner. - PoolGroupProviderInfo.FailoverCheck(this, useFailoverHost, connectionOptions, ServerProvidedFailOverPartner); + PoolGroupProviderInfo.FailoverCheck(useFailoverHost, connectionOptions, ServerProvidedFailOverPartner); } CurrentDataSource = (useFailoverHost ? failoverHost : primaryServerInfo.UserServerName); } diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlNotificationEventArgs.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlNotificationEventArgs.cs deleted file mode 100644 index 1c28c64859..0000000000 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlNotificationEventArgs.cs +++ /dev/null @@ -1,55 +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; - -namespace Microsoft.Data.SqlClient -{ - /// - public class SqlNotificationEventArgs : EventArgs - { - private SqlNotificationType _type; - private SqlNotificationInfo _info; - private SqlNotificationSource _source; - - /// - public SqlNotificationEventArgs(SqlNotificationType type, SqlNotificationInfo info, SqlNotificationSource source) - { - _info = info; - _source = source; - _type = type; - } - - /// - public SqlNotificationType Type - { - get - { - return _type; - } - } - - /// - public SqlNotificationInfo Info - { - get - { - return _info; - } - } - - /// - public SqlNotificationSource Source - { - get - { - return _source; - } - } - - internal static SqlNotificationEventArgs NotifyError = new SqlNotificationEventArgs(SqlNotificationType.Subscribe, SqlNotificationInfo.Error, SqlNotificationSource.Object); - } -} - - diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlReferenceCollection.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlReferenceCollection.cs deleted file mode 100644 index 552ba0aa3e..0000000000 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlReferenceCollection.cs +++ /dev/null @@ -1,84 +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.Diagnostics; -using Microsoft.Data.ProviderBase; - -namespace Microsoft.Data.SqlClient -{ - sealed internal class SqlReferenceCollection : DbReferenceCollection - { - internal const int DataReaderTag = 1; - internal const int CommandTag = 2; - internal const int BulkCopyTag = 3; - - override public void Add(object value, int tag) - { - Debug.Assert(DataReaderTag == tag || CommandTag == tag || BulkCopyTag == tag, "unexpected tag?"); - Debug.Assert(DataReaderTag != tag || value is SqlDataReader, "tag doesn't match object type: SqlDataReader"); - Debug.Assert(CommandTag != tag || value is SqlCommand, "tag doesn't match object type: SqlCommand"); - Debug.Assert(BulkCopyTag != tag || value is SqlBulkCopy, "tag doesn't match object type: SqlBulkCopy"); - - base.AddItem(value, tag); - } - - internal void Deactivate() - { - base.Notify(0); - } - - internal SqlDataReader FindLiveReader(SqlCommand command) - { - if (command == null) - { - // if null == command, will find first live datareader - return FindItem(DataReaderTag, (dataReader) => (!dataReader.IsClosed)); - } - else - { - // else will find live datareader assocated with the command - return FindItem(DataReaderTag, (dataReader) => ((!dataReader.IsClosed) && (command == dataReader.Command))); - } - } - - // Finds a SqlCommand associated with the given StateObject - internal SqlCommand FindLiveCommand(TdsParserStateObject stateObj) - { - return FindItem(CommandTag, (command) => (command.StateObject == stateObj)); - } - - override protected void NotifyItem(int message, int tag, object value) - { - Debug.Assert(0 == message, "unexpected message?"); - Debug.Assert(DataReaderTag == tag || CommandTag == tag || BulkCopyTag == tag, "unexpected tag?"); - - if (tag == DataReaderTag) - { - Debug.Assert(value is SqlDataReader, "Incorrect object type"); - var rdr = (SqlDataReader)value; - if (!rdr.IsClosed) - { - rdr.CloseReaderFromConnection(); - } - } - else if (tag == CommandTag) - { - Debug.Assert(value is SqlCommand, "Incorrect object type"); - ((SqlCommand)value).OnConnectionClosed(); - } - else if (tag == BulkCopyTag) - { - Debug.Assert(value is SqlBulkCopy, "Incorrect object type"); - ((SqlBulkCopy)value).OnConnectionClosed(); - } - } - - override public void Remove(object value) - { - Debug.Assert(value is SqlDataReader || value is SqlCommand || value is SqlBulkCopy, "SqlReferenceCollection.Remove expected a SqlDataReader or SqlCommand or SqlBulkCopy"); - - base.RemoveItem(value); - } - } -} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/Common/DbConnectionStringCommon.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/DbConnectionStringCommon.cs similarity index 84% rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/Common/DbConnectionStringCommon.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/DbConnectionStringCommon.cs index 0530df9cac..3cb7e0ef1c 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/Common/DbConnectionStringCommon.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/Common/DbConnectionStringCommon.cs @@ -6,18 +6,16 @@ using System.Collections.Generic; using System.Diagnostics; using System.Globalization; -using System.Reflection; using Microsoft.Data.SqlClient; namespace Microsoft.Data.Common { - internal static partial class DbConnectionStringBuilderUtil + internal static class DbConnectionStringBuilderUtil { internal static bool ConvertToBoolean(object value) { Debug.Assert(null != value, "ConvertToBoolean(null)"); - string svalue = (value as string); - if (null != svalue) + if (value is string svalue) { if (StringComparer.OrdinalIgnoreCase.Equals(svalue, "true") || StringComparer.OrdinalIgnoreCase.Equals(svalue, "yes")) return true; @@ -25,7 +23,7 @@ internal static bool ConvertToBoolean(object value) return false; else { - string tmp = svalue.Trim(); // Remove leading & trailing whitespace. + string tmp = svalue.Trim(); // Remove leading & trailing white space. if (StringComparer.OrdinalIgnoreCase.Equals(tmp, "true") || StringComparer.OrdinalIgnoreCase.Equals(tmp, "yes")) return true; else if (StringComparer.OrdinalIgnoreCase.Equals(tmp, "false") || StringComparer.OrdinalIgnoreCase.Equals(tmp, "no")) @@ -35,7 +33,7 @@ internal static bool ConvertToBoolean(object value) } try { - return Convert.ToBoolean(value); + return Convert.ToBoolean(value, CultureInfo.InvariantCulture); } catch (InvalidCastException e) { @@ -46,8 +44,7 @@ internal static bool ConvertToBoolean(object value) internal static bool ConvertToIntegratedSecurity(object value) { Debug.Assert(null != value, "ConvertToIntegratedSecurity(null)"); - string svalue = (value as string); - if (null != svalue) + if (value is string svalue) { if (StringComparer.OrdinalIgnoreCase.Equals(svalue, "sspi") || StringComparer.OrdinalIgnoreCase.Equals(svalue, "true") || StringComparer.OrdinalIgnoreCase.Equals(svalue, "yes")) return true; @@ -55,7 +52,7 @@ internal static bool ConvertToIntegratedSecurity(object value) return false; else { - string tmp = svalue.Trim(); // Remove leading & trailing whitespace. + string tmp = svalue.Trim(); // Remove leading & trailing white space. if (StringComparer.OrdinalIgnoreCase.Equals(tmp, "sspi") || StringComparer.OrdinalIgnoreCase.Equals(tmp, "true") || StringComparer.OrdinalIgnoreCase.Equals(tmp, "yes")) return true; else if (StringComparer.OrdinalIgnoreCase.Equals(tmp, "false") || StringComparer.OrdinalIgnoreCase.Equals(tmp, "no")) @@ -65,7 +62,7 @@ internal static bool ConvertToIntegratedSecurity(object value) } try { - return Convert.ToBoolean(value); + return Convert.ToBoolean(value, CultureInfo.InvariantCulture); } catch (InvalidCastException e) { @@ -77,7 +74,7 @@ internal static int ConvertToInt32(object value) { try { - return Convert.ToInt32(value); + return Convert.ToInt32(value, CultureInfo.InvariantCulture); } catch (InvalidCastException e) { @@ -89,7 +86,7 @@ internal static string ConvertToString(object value) { try { - return Convert.ToString(value); + return Convert.ToString(value, CultureInfo.InvariantCulture); } catch (InvalidCastException e) { @@ -97,301 +94,79 @@ internal static string ConvertToString(object value) } } - private const string ApplicationIntentReadWriteString = "ReadWrite"; - private const string ApplicationIntentReadOnlyString = "ReadOnly"; - - const string SqlPasswordString = "Sql Password"; - const string ActiveDirectoryPasswordString = "Active Directory Password"; - const string ActiveDirectoryIntegratedString = "Active Directory Integrated"; - const string ActiveDirectoryInteractiveString = "Active Directory Interactive"; - const string ActiveDirectoryServicePrincipalString = "Active Directory Service Principal"; - const string ActiveDirectoryDeviceCodeFlowString = "Active Directory Device Code Flow"; - internal const string ActiveDirectoryManagedIdentityString = "Active Directory Managed Identity"; - internal const string ActiveDirectoryMSIString = "Active Directory MSI"; - internal const string ActiveDirectoryDefaultString = "Active Directory Default"; - -#if DEBUG - private static string[] s_supportedAuthenticationModes = - { - "NotSpecified", - "SqlPassword", - "ActiveDirectoryPassword", - "ActiveDirectoryIntegrated", - "ActiveDirectoryInteractive", - "ActiveDirectoryServicePrincipal", - "ActiveDirectoryDeviceCodeFlow", - "ActiveDirectoryManagedIdentity", - "ActiveDirectoryMSI", - "ActiveDirectoryDefault" - }; - - private static bool IsValidAuthenticationMethodEnum() + #region <> + internal static bool TryConvertToPoolBlockingPeriod(string value, out PoolBlockingPeriod result) { - string[] names = Enum.GetNames(typeof(SqlAuthenticationMethod)); - int l = s_supportedAuthenticationModes.Length; - bool listValid; - if (listValid = names.Length == l) - { - for (int i = 0; i < l; i++) - { - if (s_supportedAuthenticationModes[i].CompareTo(names[i]) != 0) - { - listValid = false; - } - } - } - return listValid; - } -#endif + Debug.Assert(Enum.GetNames(typeof(PoolBlockingPeriod)).Length == 3, "PoolBlockingPeriod enum has changed, update needed"); + Debug.Assert(null != value, "TryConvertToPoolBlockingPeriod(null,...)"); - internal static bool TryConvertToAuthenticationType(string value, out SqlAuthenticationMethod result) - { -#if DEBUG - Debug.Assert(IsValidAuthenticationMethodEnum(), "SqlAuthenticationMethod enum has changed, update needed"); -#endif - bool isSuccess = false; - if (StringComparer.InvariantCultureIgnoreCase.Equals(value, SqlPasswordString) - || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.SqlPassword, CultureInfo.InvariantCulture))) - { - result = SqlAuthenticationMethod.SqlPassword; - isSuccess = true; - } - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryPasswordString) - || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryPassword, CultureInfo.InvariantCulture))) - { - result = SqlAuthenticationMethod.ActiveDirectoryPassword; - isSuccess = true; - } - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryIntegratedString) - || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryIntegrated, CultureInfo.InvariantCulture))) - { - result = SqlAuthenticationMethod.ActiveDirectoryIntegrated; - isSuccess = true; - } - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryInteractiveString) - || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryInteractive, CultureInfo.InvariantCulture))) - { - result = SqlAuthenticationMethod.ActiveDirectoryInteractive; - isSuccess = true; - } - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryServicePrincipalString) - || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryServicePrincipal, CultureInfo.InvariantCulture))) - { - result = SqlAuthenticationMethod.ActiveDirectoryServicePrincipal; - isSuccess = true; - } - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryDeviceCodeFlowString) - || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow, CultureInfo.InvariantCulture))) - { - result = SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow; - isSuccess = true; - } - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryManagedIdentityString) - || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, CultureInfo.InvariantCulture))) - { - result = SqlAuthenticationMethod.ActiveDirectoryManagedIdentity; - isSuccess = true; - } - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryMSIString) - || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryMSI, CultureInfo.InvariantCulture))) - { - result = SqlAuthenticationMethod.ActiveDirectoryMSI; - isSuccess = true; - } - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryDefaultString) - || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryDefault, CultureInfo.InvariantCulture))) - { - result = SqlAuthenticationMethod.ActiveDirectoryDefault; - isSuccess = true; - } - else + if (StringComparer.OrdinalIgnoreCase.Equals(value, nameof(PoolBlockingPeriod.Auto))) { - result = DbConnectionStringDefaults.Authentication; + result = PoolBlockingPeriod.Auto; + return true; } - return isSuccess; - } - - internal static bool TryConvertToApplicationIntent(string value, out ApplicationIntent result) - { - Debug.Assert(Enum.GetNames(typeof(ApplicationIntent)).Length == 2, "ApplicationIntent enum has changed, update needed"); - Debug.Assert(null != value, "TryConvertToApplicationIntent(null,...)"); - - if (StringComparer.OrdinalIgnoreCase.Equals(value, ApplicationIntentReadOnlyString)) + else if (StringComparer.OrdinalIgnoreCase.Equals(value, nameof(PoolBlockingPeriod.AlwaysBlock))) { - result = ApplicationIntent.ReadOnly; + result = PoolBlockingPeriod.AlwaysBlock; return true; } - else if (StringComparer.OrdinalIgnoreCase.Equals(value, ApplicationIntentReadWriteString)) + else if (StringComparer.OrdinalIgnoreCase.Equals(value, nameof(PoolBlockingPeriod.NeverBlock))) { - result = ApplicationIntent.ReadWrite; + result = PoolBlockingPeriod.NeverBlock; return true; } else { - result = DbConnectionStringDefaults.ApplicationIntent; + result = DbConnectionStringDefaults.PoolBlockingPeriod; return false; } } - /// - /// Column Encryption Setting. - /// - const string ColumnEncryptionSettingEnabledString = "Enabled"; - const string ColumnEncryptionSettingDisabledString = "Disabled"; - - /// - /// Convert a string value to the corresponding SqlConnectionColumnEncryptionSetting. - /// - /// - /// - /// - internal static bool TryConvertToColumnEncryptionSetting(string value, out SqlConnectionColumnEncryptionSetting result) - { - bool isSuccess = false; - - if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ColumnEncryptionSettingEnabledString)) - { - result = SqlConnectionColumnEncryptionSetting.Enabled; - isSuccess = true; - } - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ColumnEncryptionSettingDisabledString)) - { - result = SqlConnectionColumnEncryptionSetting.Disabled; - isSuccess = true; - } - else - { - result = DbConnectionStringDefaults.ColumnEncryptionSetting; - } - - return isSuccess; - } - - /// - /// Is it a valid connection level column encryption setting ? - /// - /// - /// - internal static bool IsValidColumnEncryptionSetting(SqlConnectionColumnEncryptionSetting value) + internal static bool IsValidPoolBlockingPeriodValue(PoolBlockingPeriod value) { - Debug.Assert(Enum.GetNames(typeof(SqlConnectionColumnEncryptionSetting)).Length == 2, "SqlConnectionColumnEncryptionSetting enum has changed, update needed"); - return value == SqlConnectionColumnEncryptionSetting.Enabled || value == SqlConnectionColumnEncryptionSetting.Disabled; + Debug.Assert(Enum.GetNames(typeof(PoolBlockingPeriod)).Length == 3, "PoolBlockingPeriod enum has changed, update needed"); + return value == PoolBlockingPeriod.Auto || value == PoolBlockingPeriod.AlwaysBlock || value == PoolBlockingPeriod.NeverBlock; } - /// - /// Convert connection level column encryption setting value to string. - /// - /// - /// - internal static string ColumnEncryptionSettingToString(SqlConnectionColumnEncryptionSetting value) + internal static string PoolBlockingPeriodToString(PoolBlockingPeriod value) { - Debug.Assert(IsValidColumnEncryptionSetting(value), "value is not a valid connection level column encryption setting."); + Debug.Assert(IsValidPoolBlockingPeriodValue(value)); - switch (value) + return value switch { - case SqlConnectionColumnEncryptionSetting.Enabled: - return ColumnEncryptionSettingEnabledString; - case SqlConnectionColumnEncryptionSetting.Disabled: - return ColumnEncryptionSettingDisabledString; - - default: - return null; - } + PoolBlockingPeriod.AlwaysBlock => nameof(PoolBlockingPeriod.AlwaysBlock), + PoolBlockingPeriod.NeverBlock => nameof(PoolBlockingPeriod.NeverBlock), + _ => nameof(PoolBlockingPeriod.Auto), + }; } - #region <> - - /// - /// Attestation Protocol. - /// - const string AttestationProtocolHGS = "HGS"; - const string AttestationProtocolAAS = "AAS"; -#if ENCLAVE_SIMULATOR - const string AttestationProtocolSIM = "SIM"; -#endif - /// - /// Convert a string value to the corresponding SqlConnectionAttestationProtocol + /// This method attempts to convert the given value to a PoolBlockingPeriod enum. The algorithm is: + /// * if the value is from type string, it will be matched against PoolBlockingPeriod enum names only, using ordinal, case-insensitive comparer + /// * if the value is from type PoolBlockingPeriod, it will be used as is + /// * if the value is from integral type (SByte, Int16, Int32, Int64, Byte, UInt16, UInt32, or UInt64), it will be converted to enum + /// * if the value is another enum or any other type, it will be blocked with an appropriate ArgumentException + /// + /// in any case above, if the converted value is out of valid range, the method raises ArgumentOutOfRangeException. /// - /// - /// - /// - internal static bool TryConvertToAttestationProtocol(string value, out SqlConnectionAttestationProtocol result) - { - if (StringComparer.InvariantCultureIgnoreCase.Equals(value, AttestationProtocolHGS)) - { - result = SqlConnectionAttestationProtocol.HGS; - return true; - } - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, AttestationProtocolAAS)) - { - result = SqlConnectionAttestationProtocol.AAS; - return true; - } -#if ENCLAVE_SIMULATOR - else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, AttestationProtocolSIM)) - { - result = SqlConnectionAttestationProtocol.SIM; - return true; - } -#endif - else - { - result = DbConnectionStringDefaults.AttestationProtocol; - return false; - } - } - - internal static bool IsValidAttestationProtocol(SqlConnectionAttestationProtocol value) - { -#if ENCLAVE_SIMULATOR - Debug.Assert(Enum.GetNames(typeof(SqlConnectionAttestationProtocol)).Length == 4, "SqlConnectionAttestationProtocol enum has changed, update needed"); - return value == SqlConnectionAttestationProtocol.NotSpecified - || value == SqlConnectionAttestationProtocol.HGS - || value == SqlConnectionAttestationProtocol.AAS - || value == SqlConnectionAttestationProtocol.SIM; -#else - Debug.Assert(Enum.GetNames(typeof(SqlConnectionAttestationProtocol)).Length == 3, "SqlConnectionAttestationProtocol enum has changed, update needed"); - return value == SqlConnectionAttestationProtocol.NotSpecified - || value == SqlConnectionAttestationProtocol.HGS - || value == SqlConnectionAttestationProtocol.AAS; -#endif - } - - internal static string AttestationProtocolToString(SqlConnectionAttestationProtocol value) - { - Debug.Assert(IsValidAttestationProtocol(value), "value is not a valid attestation protocol"); - - switch (value) - { - case SqlConnectionAttestationProtocol.HGS: - return AttestationProtocolHGS; - case SqlConnectionAttestationProtocol.AAS: - return AttestationProtocolAAS; -#if ENCLAVE_SIMULATOR - case SqlConnectionAttestationProtocol.SIM: - return AttestationProtocolSIM; -#endif - default: - return null; - } - } - - internal static SqlConnectionAttestationProtocol ConvertToAttestationProtocol(string keyword, object value) + /// PoolBlockingPeriod value in the valid range + internal static PoolBlockingPeriod ConvertToPoolBlockingPeriod(string keyword, object value) { - if (null == value) + Debug.Assert(null != value, "ConvertToPoolBlockingPeriod(null)"); + if (value is string sValue) { - return DbConnectionStringDefaults.AttestationProtocol; - } + // We could use Enum.TryParse here, but it accepts value combinations like + // "ReadOnly, ReadWrite" which are unwelcome here + // Also, Enum.TryParse is 100x slower than plain StringComparer.OrdinalIgnoreCase.Equals method. - string sValue = (value as string); - SqlConnectionAttestationProtocol result; + if (TryConvertToPoolBlockingPeriod(sValue, out PoolBlockingPeriod result)) + { + return result; + } - if (null != sValue) - { // try again after remove leading & trailing whitespaces. sValue = sValue.Trim(); - if (TryConvertToAttestationProtocol(sValue, out result)) + if (TryConvertToPoolBlockingPeriod(sValue, out result)) { return result; } @@ -402,150 +177,69 @@ internal static SqlConnectionAttestationProtocol ConvertToAttestationProtocol(st else { // the value is not string, try other options - SqlConnectionAttestationProtocol eValue; + PoolBlockingPeriod eValue; - if (value is SqlConnectionAttestationProtocol) + if (value is PoolBlockingPeriod period) { - eValue = (SqlConnectionAttestationProtocol)value; + // quick path for the most common case + eValue = period; } else if (value.GetType().IsEnum) { // explicitly block scenarios in which user tries to use wrong enum types, like: - // builder["SqlConnectionAttestationProtocol"] = EnvironmentVariableTarget.Process; - // workaround: explicitly cast non-SqlConnectionAttestationProtocol enums to int - throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionAttestationProtocol), null); + // builder["PoolBlockingPeriod"] = EnvironmentVariableTarget.Process; + // workaround: explicitly cast non-PoolBlockingPeriod enums to int + throw ADP.ConvertFailed(value.GetType(), typeof(PoolBlockingPeriod), null); } else { try { // Enum.ToObject allows only integral and enum values (enums are blocked above), raising ArgumentException for the rest - eValue = (SqlConnectionAttestationProtocol)Enum.ToObject(typeof(SqlConnectionAttestationProtocol), value); + eValue = (PoolBlockingPeriod)Enum.ToObject(typeof(PoolBlockingPeriod), value); } catch (ArgumentException e) { // to be consistent with the messages we send in case of wrong type usage, replace // the error with our exception, and keep the original one as inner one for troubleshooting - throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionAttestationProtocol), e); + throw ADP.ConvertFailed(value.GetType(), typeof(PoolBlockingPeriod), e); } } - if (IsValidAttestationProtocol(eValue)) + // ensure value is in valid range + if (IsValidPoolBlockingPeriodValue(eValue)) { return eValue; } else { - throw ADP.InvalidEnumerationValue(typeof(SqlConnectionAttestationProtocol), (int)eValue); + throw ADP.InvalidEnumerationValue(typeof(ApplicationIntent), (int)eValue); } } } - #endregion - #region <> - /// - /// IP Address Preference. - /// - private readonly static Dictionary s_preferenceNames = new(StringComparer.InvariantCultureIgnoreCase); - - static DbConnectionStringBuilderUtil() - { - foreach (SqlConnectionIPAddressPreference item in Enum.GetValues(typeof(SqlConnectionIPAddressPreference))) - { - s_preferenceNames.Add(item.ToString(), item); - } - } - - /// - /// Convert a string value to the corresponding IPAddressPreference. - /// - /// The string representation of the enumeration name to convert. - /// When this method returns, `result` contains an object of type `SqlConnectionIPAddressPreference` whose value is represented by `value` if the operation succeeds. - /// If the parse operation fails, `result` contains the default value of the `SqlConnectionIPAddressPreference` type. - /// `true` if the value parameter was converted successfully; otherwise, `false`. - internal static bool TryConvertToIPAddressPreference(string value, out SqlConnectionIPAddressPreference result) + internal static bool TryConvertToApplicationIntent(string value, out ApplicationIntent result) { - if (!s_preferenceNames.TryGetValue(value, out result)) - { - result = DbConnectionStringDefaults.IPAddressPreference; - return false; - } - return true; - } - - /// - /// Verifies if the `value` is defined in the expected Enum. - /// - internal static bool IsValidIPAddressPreference(SqlConnectionIPAddressPreference value) - => value == SqlConnectionIPAddressPreference.IPv4First - || value == SqlConnectionIPAddressPreference.IPv6First - || value == SqlConnectionIPAddressPreference.UsePlatformDefault; - - internal static string IPAddressPreferenceToString(SqlConnectionIPAddressPreference value) - => Enum.GetName(typeof(SqlConnectionIPAddressPreference), value); + Debug.Assert(Enum.GetNames(typeof(ApplicationIntent)).Length == 2, "ApplicationIntent enum has changed, update needed"); + Debug.Assert(null != value, "TryConvertToApplicationIntent(null,...)"); - internal static SqlConnectionIPAddressPreference ConvertToIPAddressPreference(string keyword, object value) - { - if (value is null) + if (StringComparer.OrdinalIgnoreCase.Equals(value, nameof(ApplicationIntent.ReadOnly))) { - return DbConnectionStringDefaults.IPAddressPreference; // IPv4First + result = ApplicationIntent.ReadOnly; + return true; } - - if (value is string sValue) + else if (StringComparer.OrdinalIgnoreCase.Equals(value, nameof(ApplicationIntent.ReadWrite))) { - // try again after remove leading & trailing whitespaces. - sValue = sValue.Trim(); - if (TryConvertToIPAddressPreference(sValue, out SqlConnectionIPAddressPreference result)) - { - return result; - } - - // string values must be valid - throw ADP.InvalidConnectionOptionValue(keyword); + result = ApplicationIntent.ReadWrite; + return true; } else { - // the value is not string, try other options - SqlConnectionIPAddressPreference eValue; - - if (value is SqlConnectionIPAddressPreference preference) - { - eValue = preference; - } - else if (value.GetType().IsEnum) - { - // explicitly block scenarios in which user tries to use wrong enum types, like: - // builder["SqlConnectionIPAddressPreference"] = EnvironmentVariableTarget.Process; - // workaround: explicitly cast non-SqlConnectionIPAddressPreference enums to int - throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionIPAddressPreference), null); - } - else - { - try - { - // Enum.ToObject allows only integral and enum values (enums are blocked above), raising ArgumentException for the rest - eValue = (SqlConnectionIPAddressPreference)Enum.ToObject(typeof(SqlConnectionIPAddressPreference), value); - } - catch (ArgumentException e) - { - // to be consistent with the messages we send in case of wrong type usage, replace - // the error with our exception, and keep the original one as inner one for troubleshooting - throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionIPAddressPreference), e); - } - } - - if (IsValidIPAddressPreference(eValue)) - { - return eValue; - } - else - { - throw ADP.InvalidEnumerationValue(typeof(SqlConnectionIPAddressPreference), (int)eValue); - } + result = DbConnectionStringDefaults.ApplicationIntent; + return false; } } - #endregion internal static bool IsValidApplicationIntentValue(ApplicationIntent value) { @@ -558,11 +252,11 @@ internal static string ApplicationIntentToString(ApplicationIntent value) Debug.Assert(IsValidApplicationIntentValue(value)); if (value == ApplicationIntent.ReadOnly) { - return ApplicationIntentReadOnlyString; + return nameof(ApplicationIntent.ReadOnly); } else { - return ApplicationIntentReadWriteString; + return nameof(ApplicationIntent.ReadWrite); } } @@ -579,20 +273,18 @@ internal static string ApplicationIntentToString(ApplicationIntent value) internal static ApplicationIntent ConvertToApplicationIntent(string keyword, object value) { Debug.Assert(null != value, "ConvertToApplicationIntent(null)"); - string sValue = (value as string); - ApplicationIntent result; - if (null != sValue) + if (value is string sValue) { // We could use Enum.TryParse here, but it accepts value combinations like // "ReadOnly, ReadWrite" which are unwelcome here // Also, Enum.TryParse is 100x slower than plain StringComparer.OrdinalIgnoreCase.Equals method. - if (TryConvertToApplicationIntent(sValue, out result)) + if (TryConvertToApplicationIntent(sValue, out ApplicationIntent result)) { return result; } - // try again after remove leading & trailing whitespace. + // try again after remove leading & trailing whitespaces. sValue = sValue.Trim(); if (TryConvertToApplicationIntent(sValue, out result)) { @@ -607,12 +299,12 @@ internal static ApplicationIntent ConvertToApplicationIntent(string keyword, obj // the value is not string, try other options ApplicationIntent eValue; - if (value is ApplicationIntent) + if (value is ApplicationIntent intent) { // quick path for the most common case - eValue = (ApplicationIntent)value; + eValue = intent; } - else if (value.GetType().GetTypeInfo().IsEnum) + else if (value.GetType().IsEnum) { // explicitly block scenarios in which user tries to use wrong enum types, like: // builder["ApplicationIntent"] = EnvironmentVariableTarget.Process; @@ -646,6 +338,182 @@ internal static ApplicationIntent ConvertToApplicationIntent(string keyword, obj } } + const string SqlPasswordString = "Sql Password"; + const string ActiveDirectoryPasswordString = "Active Directory Password"; + const string ActiveDirectoryIntegratedString = "Active Directory Integrated"; + const string ActiveDirectoryInteractiveString = "Active Directory Interactive"; + const string ActiveDirectoryServicePrincipalString = "Active Directory Service Principal"; + const string ActiveDirectoryDeviceCodeFlowString = "Active Directory Device Code Flow"; + internal const string ActiveDirectoryManagedIdentityString = "Active Directory Managed Identity"; + internal const string ActiveDirectoryMSIString = "Active Directory MSI"; + internal const string ActiveDirectoryDefaultString = "Active Directory Default"; + const string SqlCertificateString = "Sql Certificate"; + +#if DEBUG + private static readonly string[] s_supportedAuthenticationModes = + { + "NotSpecified", + "SqlPassword", + "ActiveDirectoryPassword", + "ActiveDirectoryIntegrated", + "ActiveDirectoryInteractive", + "ActiveDirectoryServicePrincipal", + "ActiveDirectoryDeviceCodeFlow", + "ActiveDirectoryManagedIdentity", + "ActiveDirectoryMSI", + "ActiveDirectoryDefault" + }; + + private static bool IsValidAuthenticationMethodEnum() + { + string[] names = Enum.GetNames(typeof(SqlAuthenticationMethod)); + int l = s_supportedAuthenticationModes.Length; + bool listValid; + if (listValid = names.Length == l) + { + for (int i = 0; i < l; i++) + { + if (s_supportedAuthenticationModes[i].CompareTo(names[i]) != 0) + { + listValid = false; + } + } + } + return listValid; + } +#endif + + internal static bool TryConvertToAuthenticationType(string value, out SqlAuthenticationMethod result) + { +#if DEBUG + Debug.Assert(IsValidAuthenticationMethodEnum(), "SqlAuthenticationMethod enum has changed, update needed"); +#endif + bool isSuccess = false; + + if (StringComparer.InvariantCultureIgnoreCase.Equals(value, SqlPasswordString) + || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.SqlPassword, CultureInfo.InvariantCulture))) + { + result = SqlAuthenticationMethod.SqlPassword; + isSuccess = true; + } + else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryPasswordString) + || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryPassword, CultureInfo.InvariantCulture))) + { + result = SqlAuthenticationMethod.ActiveDirectoryPassword; + isSuccess = true; + } + else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryIntegratedString) + || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryIntegrated, CultureInfo.InvariantCulture))) + { + result = SqlAuthenticationMethod.ActiveDirectoryIntegrated; + isSuccess = true; + } + else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryInteractiveString) + || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryInteractive, CultureInfo.InvariantCulture))) + { + result = SqlAuthenticationMethod.ActiveDirectoryInteractive; + isSuccess = true; + } + else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryServicePrincipalString) + || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryServicePrincipal, CultureInfo.InvariantCulture))) + { + result = SqlAuthenticationMethod.ActiveDirectoryServicePrincipal; + isSuccess = true; + } + else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryDeviceCodeFlowString) + || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow, CultureInfo.InvariantCulture))) + { + result = SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow; + isSuccess = true; + } + else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryManagedIdentityString) + || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryManagedIdentity, CultureInfo.InvariantCulture))) + { + result = SqlAuthenticationMethod.ActiveDirectoryManagedIdentity; + isSuccess = true; + } + else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryMSIString) + || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryMSI, CultureInfo.InvariantCulture))) + { + result = SqlAuthenticationMethod.ActiveDirectoryMSI; + isSuccess = true; + } + else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, ActiveDirectoryDefaultString) + || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.ActiveDirectoryDefault, CultureInfo.InvariantCulture))) + { + result = SqlAuthenticationMethod.ActiveDirectoryDefault; + isSuccess = true; + } +#if ADONET_CERT_AUTH && NETFRAMEWORK + else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, SqlCertificateString) + || StringComparer.InvariantCultureIgnoreCase.Equals(value, Convert.ToString(SqlAuthenticationMethod.SqlCertificate, CultureInfo.InvariantCulture))) { + result = SqlAuthenticationMethod.SqlCertificate; + isSuccess = true; + } +#endif + else + { + result = DbConnectionStringDefaults.Authentication; + } + return isSuccess; + } + + /// + /// Convert a string value to the corresponding SqlConnectionColumnEncryptionSetting. + /// + /// + /// + /// + internal static bool TryConvertToColumnEncryptionSetting(string value, out SqlConnectionColumnEncryptionSetting result) + { + bool isSuccess = false; + + if (StringComparer.InvariantCultureIgnoreCase.Equals(value, nameof(SqlConnectionColumnEncryptionSetting.Enabled))) + { + result = SqlConnectionColumnEncryptionSetting.Enabled; + isSuccess = true; + } + else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, nameof(SqlConnectionColumnEncryptionSetting.Disabled))) + { + result = SqlConnectionColumnEncryptionSetting.Disabled; + isSuccess = true; + } + else + { + result = DbConnectionStringDefaults.ColumnEncryptionSetting; + } + + return isSuccess; + } + + /// + /// Is it a valid connection level column encryption setting ? + /// + /// + /// + internal static bool IsValidColumnEncryptionSetting(SqlConnectionColumnEncryptionSetting value) + { + Debug.Assert(Enum.GetNames(typeof(SqlConnectionColumnEncryptionSetting)).Length == 2, "SqlConnectionColumnEncryptionSetting enum has changed, update needed"); + return value == SqlConnectionColumnEncryptionSetting.Enabled || value == SqlConnectionColumnEncryptionSetting.Disabled; + } + + /// + /// Convert connection level column encryption setting value to string. + /// + /// + /// + internal static string ColumnEncryptionSettingToString(SqlConnectionColumnEncryptionSetting value) + { + Debug.Assert(IsValidColumnEncryptionSetting(value), "value is not a valid connection level column encryption setting."); + + return value switch + { + SqlConnectionColumnEncryptionSetting.Enabled => nameof(SqlConnectionColumnEncryptionSetting.Enabled), + SqlConnectionColumnEncryptionSetting.Disabled => nameof(SqlConnectionColumnEncryptionSetting.Disabled), + _ => null, + }; + } + internal static bool IsValidAuthenticationTypeValue(SqlAuthenticationMethod value) { Debug.Assert(Enum.GetNames(typeof(SqlAuthenticationMethod)).Length == 10, "SqlAuthenticationMethod enum has changed, update needed"); @@ -658,6 +526,9 @@ internal static bool IsValidAuthenticationTypeValue(SqlAuthenticationMethod valu || value == SqlAuthenticationMethod.ActiveDirectoryManagedIdentity || value == SqlAuthenticationMethod.ActiveDirectoryMSI || value == SqlAuthenticationMethod.ActiveDirectoryDefault +#if ADONET_CERT_AUTH && NETFRAMEWORK + || value == SqlAuthenticationMethod.SqlCertificate +#endif || value == SqlAuthenticationMethod.NotSpecified; } @@ -665,29 +536,22 @@ internal static string AuthenticationTypeToString(SqlAuthenticationMethod value) { Debug.Assert(IsValidAuthenticationTypeValue(value)); - switch (value) + return value switch { - case SqlAuthenticationMethod.SqlPassword: - return SqlPasswordString; - case SqlAuthenticationMethod.ActiveDirectoryPassword: - return ActiveDirectoryPasswordString; - case SqlAuthenticationMethod.ActiveDirectoryIntegrated: - return ActiveDirectoryIntegratedString; - case SqlAuthenticationMethod.ActiveDirectoryInteractive: - return ActiveDirectoryInteractiveString; - case SqlAuthenticationMethod.ActiveDirectoryServicePrincipal: - return ActiveDirectoryServicePrincipalString; - case SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow: - return ActiveDirectoryDeviceCodeFlowString; - case SqlAuthenticationMethod.ActiveDirectoryManagedIdentity: - return ActiveDirectoryManagedIdentityString; - case SqlAuthenticationMethod.ActiveDirectoryMSI: - return ActiveDirectoryMSIString; - case SqlAuthenticationMethod.ActiveDirectoryDefault: - return ActiveDirectoryDefaultString; - default: - return null; - } + SqlAuthenticationMethod.SqlPassword => SqlPasswordString, + SqlAuthenticationMethod.ActiveDirectoryPassword => ActiveDirectoryPasswordString, + SqlAuthenticationMethod.ActiveDirectoryIntegrated => ActiveDirectoryIntegratedString, + SqlAuthenticationMethod.ActiveDirectoryInteractive => ActiveDirectoryInteractiveString, + SqlAuthenticationMethod.ActiveDirectoryServicePrincipal => ActiveDirectoryServicePrincipalString, + SqlAuthenticationMethod.ActiveDirectoryDeviceCodeFlow => ActiveDirectoryDeviceCodeFlowString, + SqlAuthenticationMethod.ActiveDirectoryManagedIdentity => ActiveDirectoryManagedIdentityString, + SqlAuthenticationMethod.ActiveDirectoryMSI => ActiveDirectoryMSIString, + SqlAuthenticationMethod.ActiveDirectoryDefault => ActiveDirectoryDefaultString, +#if ADONET_CERT_AUTH && NETFRAMEWORK + SqlAuthenticationMethod.SqlCertificate => SqlCertificateString, +#endif + _ => null + }; } internal static SqlAuthenticationMethod ConvertToAuthenticationType(string keyword, object value) @@ -697,11 +561,9 @@ internal static SqlAuthenticationMethod ConvertToAuthenticationType(string keywo return DbConnectionStringDefaults.Authentication; } - string sValue = (value as string); - SqlAuthenticationMethod result; - if (null != sValue) + if (value is string sValue) { - if (TryConvertToAuthenticationType(sValue, out result)) + if (TryConvertToAuthenticationType(sValue, out SqlAuthenticationMethod result)) { return result; } @@ -721,10 +583,10 @@ internal static SqlAuthenticationMethod ConvertToAuthenticationType(string keywo // the value is not string, try other options SqlAuthenticationMethod eValue; - if (value is SqlAuthenticationMethod) + if (value is SqlAuthenticationMethod method) { // quick path for the most common case - eValue = (SqlAuthenticationMethod)value; + eValue = method; } else if (value.GetType().IsEnum) { @@ -773,11 +635,9 @@ internal static SqlConnectionColumnEncryptionSetting ConvertToColumnEncryptionSe return DbConnectionStringDefaults.ColumnEncryptionSetting; } - string sValue = (value as string); - SqlConnectionColumnEncryptionSetting result; - if (null != sValue) + if (value is string sValue) { - if (TryConvertToColumnEncryptionSetting(sValue, out result)) + if (TryConvertToColumnEncryptionSetting(sValue, out SqlConnectionColumnEncryptionSetting result)) { return result; } @@ -797,10 +657,10 @@ internal static SqlConnectionColumnEncryptionSetting ConvertToColumnEncryptionSe // the value is not string, try other options SqlConnectionColumnEncryptionSetting eValue; - if (value is SqlConnectionColumnEncryptionSetting) + if (value is SqlConnectionColumnEncryptionSetting setting) { // quick path for the most common case - eValue = (SqlConnectionColumnEncryptionSetting)value; + eValue = setting; } else if (value.GetType().IsEnum) { @@ -836,83 +696,187 @@ internal static SqlConnectionColumnEncryptionSetting ConvertToColumnEncryptionSe } } - #region <> - internal static bool TryConvertToPoolBlockingPeriod(string value, out PoolBlockingPeriod result) + #region <> + /// + /// Convert a string value to the corresponding SqlConnectionAttestationProtocol + /// + /// + /// + /// + internal static bool TryConvertToAttestationProtocol(string value, out SqlConnectionAttestationProtocol result) { - Debug.Assert(Enum.GetNames(typeof(PoolBlockingPeriod)).Length == 3, "PoolBlockingPeriod enum has changed, update needed"); - Debug.Assert(null != value, "TryConvertToPoolBlockingPeriod(null,...)"); - - if (StringComparer.OrdinalIgnoreCase.Equals(value, nameof(PoolBlockingPeriod.Auto))) + if (StringComparer.InvariantCultureIgnoreCase.Equals(value, nameof(SqlConnectionAttestationProtocol.HGS))) { - result = PoolBlockingPeriod.Auto; + result = SqlConnectionAttestationProtocol.HGS; return true; } - else if (StringComparer.OrdinalIgnoreCase.Equals(value, nameof(PoolBlockingPeriod.AlwaysBlock))) + else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, nameof(SqlConnectionAttestationProtocol.AAS))) { - result = PoolBlockingPeriod.AlwaysBlock; + result = SqlConnectionAttestationProtocol.AAS; return true; } - else if (StringComparer.OrdinalIgnoreCase.Equals(value, nameof(PoolBlockingPeriod.NeverBlock))) +#if ENCLAVE_SIMULATOR + else if (StringComparer.InvariantCultureIgnoreCase.Equals(value, nameof(SqlConnectionAttestationProtocol.SIM))) { - result = PoolBlockingPeriod.NeverBlock; + result = SqlConnectionAttestationProtocol.SIM; return true; } +#endif else { - result = DbConnectionStringDefaults.PoolBlockingPeriod; + result = DbConnectionStringDefaults.AttestationProtocol; return false; } } - internal static bool IsValidPoolBlockingPeriodValue(PoolBlockingPeriod value) + internal static bool IsValidAttestationProtocol(SqlConnectionAttestationProtocol value) { - Debug.Assert(Enum.GetNames(typeof(PoolBlockingPeriod)).Length == 3, "PoolBlockingPeriod enum has changed, update needed"); - return (uint)value <= (uint)PoolBlockingPeriod.NeverBlock; +#if ENCLAVE_SIMULATOR + Debug.Assert(Enum.GetNames(typeof(SqlConnectionAttestationProtocol)).Length == 4, "SqlConnectionAttestationProtocol enum has changed, update needed"); + return value == SqlConnectionAttestationProtocol.NotSpecified + || value == SqlConnectionAttestationProtocol.HGS + || value == SqlConnectionAttestationProtocol.AAS + || value == SqlConnectionAttestationProtocol.SIM; +#else + Debug.Assert(Enum.GetNames(typeof(SqlConnectionAttestationProtocol)).Length == 3, "SqlConnectionAttestationProtocol enum has changed, update needed"); + return value == SqlConnectionAttestationProtocol.NotSpecified + || value == SqlConnectionAttestationProtocol.HGS + || value == SqlConnectionAttestationProtocol.AAS; +#endif } - internal static string PoolBlockingPeriodToString(PoolBlockingPeriod value) + internal static string AttestationProtocolToString(SqlConnectionAttestationProtocol value) { - Debug.Assert(IsValidPoolBlockingPeriodValue(value)); + Debug.Assert(IsValidAttestationProtocol(value), "value is not a valid attestation protocol"); - switch (value) + return value switch { - case PoolBlockingPeriod.AlwaysBlock: - return nameof(PoolBlockingPeriod.AlwaysBlock); - case PoolBlockingPeriod.NeverBlock: - return nameof(PoolBlockingPeriod.NeverBlock); - default: - return nameof(PoolBlockingPeriod.Auto); - } + SqlConnectionAttestationProtocol.AAS => nameof(SqlConnectionAttestationProtocol.AAS), + SqlConnectionAttestationProtocol.HGS => nameof(SqlConnectionAttestationProtocol.HGS), +#if ENCLAVE_SIMULATOR + SqlConnectionAttestationProtocol.SIM => nameof(SqlConnectionAttestationProtocol.SIM), +#endif + _ => null + }; } - /// - /// This method attempts to convert the given value to a PoolBlockingPeriod enum. The algorithm is: - /// * if the value is from type string, it will be matched against PoolBlockingPeriod enum names only, using ordinal, case-insensitive comparer - /// * if the value is from type PoolBlockingPeriod, it will be used as is - /// * if the value is from integral type (SByte, Int16, Int32, Int64, Byte, UInt16, UInt32, or UInt64), it will be converted to enum - /// * if the value is another enum or any other type, it will be blocked with an appropriate ArgumentException - /// - /// in any case above, if the converted value is out of valid range, the method raises ArgumentOutOfRangeException. - /// - /// PoolBlockingPeriod value in the valid range - internal static PoolBlockingPeriod ConvertToPoolBlockingPeriod(string keyword, object value) + internal static SqlConnectionAttestationProtocol ConvertToAttestationProtocol(string keyword, object value) { - Debug.Assert(null != value, "ConvertToPoolBlockingPeriod(null)"); - string sValue = (value as string); - PoolBlockingPeriod result; - if (null != sValue) + if (null == value) { - // We could use Enum.TryParse here, but it accepts value combinations like - // "ReadOnly, ReadWrite" which are unwelcome here - // Also, Enum.TryParse is 100x slower than plain StringComparer.OrdinalIgnoreCase.Equals method. - if (TryConvertToPoolBlockingPeriod(sValue, out result)) + return DbConnectionStringDefaults.AttestationProtocol; + } + + if (value is string sValue) + { + // try again after remove leading & trailing whitespaces. + sValue = sValue.Trim(); + if (TryConvertToAttestationProtocol(sValue, out SqlConnectionAttestationProtocol result)) { return result; } + // string values must be valid + throw ADP.InvalidConnectionOptionValue(keyword); + } + else + { + // the value is not string, try other options + SqlConnectionAttestationProtocol eValue; + + if (value is SqlConnectionAttestationProtocol protocol) + { + eValue = protocol; + } + else if (value.GetType().IsEnum) + { + // explicitly block scenarios in which user tries to use wrong enum types, like: + // builder["SqlConnectionAttestationProtocol"] = EnvironmentVariableTarget.Process; + // workaround: explicitly cast non-SqlConnectionAttestationProtocol enums to int + throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionAttestationProtocol), null); + } + else + { + try + { + // Enum.ToObject allows only integral and enum values (enums are blocked above), raising ArgumentException for the rest + eValue = (SqlConnectionAttestationProtocol)Enum.ToObject(typeof(SqlConnectionAttestationProtocol), value); + } + catch (ArgumentException e) + { + // to be consistent with the messages we send in case of wrong type usage, replace + // the error with our exception, and keep the original one as inner one for troubleshooting + throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionAttestationProtocol), e); + } + } + + if (IsValidAttestationProtocol(eValue)) + { + return eValue; + } + else + { + throw ADP.InvalidEnumerationValue(typeof(SqlConnectionAttestationProtocol), (int)eValue); + } + } + } + + #endregion + + #region <> + /// + /// IP Address Preference. + /// + private readonly static Dictionary s_preferenceNames = new(StringComparer.InvariantCultureIgnoreCase); + + static DbConnectionStringBuilderUtil() + { + foreach (SqlConnectionIPAddressPreference item in Enum.GetValues(typeof(SqlConnectionIPAddressPreference))) + { + s_preferenceNames.Add(item.ToString(), item); + } + } + + /// + /// Convert a string value to the corresponding IPAddressPreference. + /// + /// The string representation of the enumeration name to convert. + /// When this method returns, `result` contains an object of type `SqlConnectionIPAddressPreference` whose value is represented by `value` if the operation succeeds. + /// If the parse operation fails, `result` contains the default value of the `SqlConnectionIPAddressPreference` type. + /// `true` if the value parameter was converted successfully; otherwise, `false`. + internal static bool TryConvertToIPAddressPreference(string value, out SqlConnectionIPAddressPreference result) + { + if (!s_preferenceNames.TryGetValue(value, out result)) + { + result = DbConnectionStringDefaults.IPAddressPreference; + return false; + } + return true; + } + + /// + /// Verifies if the `value` is defined in the expected Enum. + /// + internal static bool IsValidIPAddressPreference(SqlConnectionIPAddressPreference value) + => value == SqlConnectionIPAddressPreference.IPv4First + || value == SqlConnectionIPAddressPreference.IPv6First + || value == SqlConnectionIPAddressPreference.UsePlatformDefault; + + internal static string IPAddressPreferenceToString(SqlConnectionIPAddressPreference value) + => Enum.GetName(typeof(SqlConnectionIPAddressPreference), value); + + internal static SqlConnectionIPAddressPreference ConvertToIPAddressPreference(string keyword, object value) + { + if (value is null) + { + return DbConnectionStringDefaults.IPAddressPreference; // IPv4First + } + + if (value is string sValue) + { // try again after remove leading & trailing whitespaces. sValue = sValue.Trim(); - if (TryConvertToPoolBlockingPeriod(sValue, out result)) + if (TryConvertToIPAddressPreference(sValue, out SqlConnectionIPAddressPreference result)) { return result; } @@ -923,67 +887,81 @@ internal static PoolBlockingPeriod ConvertToPoolBlockingPeriod(string keyword, o else { // the value is not string, try other options - PoolBlockingPeriod eValue; + SqlConnectionIPAddressPreference eValue; - if (value is PoolBlockingPeriod) + if (value is SqlConnectionIPAddressPreference preference) { - // quick path for the most common case - eValue = (PoolBlockingPeriod)value; + eValue = preference; } else if (value.GetType().IsEnum) { // explicitly block scenarios in which user tries to use wrong enum types, like: - // builder["PoolBlockingPeriod"] = EnvironmentVariableTarget.Process; - // workaround: explicitly cast non-PoolBlockingPeriod enums to int - throw ADP.ConvertFailed(value.GetType(), typeof(PoolBlockingPeriod), null); + // builder["SqlConnectionIPAddressPreference"] = EnvironmentVariableTarget.Process; + // workaround: explicitly cast non-SqlConnectionIPAddressPreference enums to int + throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionIPAddressPreference), null); } else { try { // Enum.ToObject allows only integral and enum values (enums are blocked above), raising ArgumentException for the rest - eValue = (PoolBlockingPeriod)Enum.ToObject(typeof(PoolBlockingPeriod), value); + eValue = (SqlConnectionIPAddressPreference)Enum.ToObject(typeof(SqlConnectionIPAddressPreference), value); } catch (ArgumentException e) { - // to be consistent with the messages we send in case of wrong type usage, replace + // to be consistent with the messages we send in case of wrong type usage, replace // the error with our exception, and keep the original one as inner one for troubleshooting - throw ADP.ConvertFailed(value.GetType(), typeof(PoolBlockingPeriod), e); + throw ADP.ConvertFailed(value.GetType(), typeof(SqlConnectionIPAddressPreference), e); } } - // ensure value is in valid range - if (IsValidPoolBlockingPeriodValue(eValue)) + if (IsValidIPAddressPreference(eValue)) { return eValue; } else { - throw ADP.InvalidEnumerationValue(typeof(ApplicationIntent), (int)eValue); + throw ADP.InvalidEnumerationValue(typeof(SqlConnectionIPAddressPreference), (int)eValue); } } } #endregion + +#if ADONET_CERT_AUTH && NETFRAMEWORK + internal static bool IsValidCertificateValue(string value) => string.IsNullOrEmpty(value) + || value.StartsWith("subject:", StringComparison.OrdinalIgnoreCase) + || value.StartsWith("sha1:", StringComparison.OrdinalIgnoreCase); +#endif } - internal static partial class DbConnectionStringDefaults + internal static class DbConnectionStringDefaults { - // all - // internal const string NamedConnection = ""; - - private const string _emptyString = ""; - // SqlClient internal const ApplicationIntent ApplicationIntent = Microsoft.Data.SqlClient.ApplicationIntent.ReadWrite; - internal const string ApplicationName = "Core Microsoft SqlClient Data Provider"; - internal const string AttachDBFilename = _emptyString; + internal const string ApplicationName = +#if NETFRAMEWORK + "Framework Microsoft SqlClient Data Provider"; +#else + "Core Microsoft SqlClient Data Provider"; +#endif + internal const string AttachDBFilename = ""; internal const int CommandTimeout = 30; internal const int ConnectTimeout = 15; - internal const string CurrentLanguage = _emptyString; - internal const string DataSource = _emptyString; - internal const bool Encrypt = false; + +#if NETFRAMEWORK + internal const bool ConnectionReset = true; + internal const bool ContextConnection = false; + internal static readonly bool TransparentNetworkIPResolution = !LocalAppContextSwitches.DisableTNIRByDefault; + internal const string NetworkLibrary = ""; +#if ADONET_CERT_AUTH + internal const string Certificate = ""; +#endif +#endif + internal const string CurrentLanguage = ""; + internal const string DataSource = ""; + internal const bool Encrypt = true; internal const bool Enlist = true; - internal const string FailoverPartner = _emptyString; - internal const string InitialCatalog = _emptyString; + internal const string FailoverPartner = ""; + internal const string InitialCatalog = ""; internal const bool IntegratedSecurity = false; internal const int LoadBalanceTimeout = 0; // default of 0 means don't use internal const bool MultipleActiveResultSets = false; @@ -991,37 +969,54 @@ internal static partial class DbConnectionStringDefaults internal const int MaxPoolSize = 100; internal const int MinPoolSize = 0; internal const int PacketSize = 8000; - internal const string Password = _emptyString; + internal const string Password = ""; internal const bool PersistSecurityInfo = false; internal const bool Pooling = true; internal const bool TrustServerCertificate = false; internal const string TypeSystemVersion = "Latest"; - internal const string UserID = _emptyString; + internal const string UserID = ""; internal const bool UserInstance = false; internal const bool Replication = false; - internal const string WorkstationID = _emptyString; + internal const string WorkstationID = ""; internal const string TransactionBinding = "Implicit Unbind"; internal const int ConnectRetryCount = 1; internal const int ConnectRetryInterval = 10; - internal const PoolBlockingPeriod PoolBlockingPeriod = Microsoft.Data.SqlClient.PoolBlockingPeriod.Auto; internal static readonly SqlAuthenticationMethod Authentication = SqlAuthenticationMethod.NotSpecified; - internal const SqlConnectionColumnEncryptionSetting ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Disabled; - internal const string EnclaveAttestationUrl = _emptyString; + internal static readonly SqlConnectionColumnEncryptionSetting ColumnEncryptionSetting = SqlConnectionColumnEncryptionSetting.Disabled; + internal const string EnclaveAttestationUrl = ""; internal const SqlConnectionAttestationProtocol AttestationProtocol = SqlConnectionAttestationProtocol.NotSpecified; internal const SqlConnectionIPAddressPreference IPAddressPreference = SqlConnectionIPAddressPreference.IPv4First; + internal const PoolBlockingPeriod PoolBlockingPeriod = SqlClient.PoolBlockingPeriod.Auto; } - internal static partial class DbConnectionStringKeywords + internal static class DbConnectionStringKeywords { - // all - // internal const string NamedConnection = "Named Connection"; +#if NETFRAMEWORK + // Odbc + internal const string Driver = "Driver"; + internal const string Dsn = "Dsn"; + internal const string FileDsn = "FileDsn"; + internal const string SaveFile = "SaveFile"; + // OleDb + internal const string FileName = "File Name"; + internal const string OleDbServices = "OLE DB Services"; + internal const string Provider = "Provider"; + + // OracleClient + internal const string Unicode = "Unicode"; + internal const string OmitOracleConnectionName = "Omit Oracle Connection Name"; + + // SqlClient + internal const string TransparentNetworkIPResolution = "Transparent Network IP Resolution"; + internal const string Certificate = "Certificate"; +#endif // SqlClient internal const string ApplicationIntent = "Application Intent"; internal const string ApplicationName = "Application Name"; internal const string AttachDBFilename = "AttachDbFilename"; - internal const string CommandTimeout = "Command Timeout"; internal const string ConnectTimeout = "Connect Timeout"; + internal const string CommandTimeout = "Command Timeout"; internal const string ConnectionReset = "Connection Reset"; internal const string ContextConnection = "Context Connection"; internal const string CurrentLanguage = "Current Language"; @@ -1050,7 +1045,6 @@ internal static partial class DbConnectionStringKeywords internal const string DataSource = "Data Source"; internal const string IntegratedSecurity = "Integrated Security"; internal const string Password = "Password"; - internal const string Driver = "Driver"; internal const string PersistSecurityInfo = "Persist Security Info"; internal const string UserID = "User ID"; @@ -1065,14 +1059,18 @@ internal static partial class DbConnectionStringKeywords internal static class DbConnectionStringSynonyms { +#if NETFRAMEWORK + //internal const string TransparentNetworkIPResolution = TRANSPARENTNETWORKIPRESOLUTION; + internal const string TRANSPARENTNETWORKIPRESOLUTION = "transparentnetworkipresolution"; +#endif //internal const string ApplicationName = APP; internal const string APP = "app"; // internal const string IPAddressPreference = IPADDRESSPREFERENCE; - internal const string IPADDRESSPREFERENCE = "IPAddressPreference"; + internal const string IPADDRESSPREFERENCE = "ipaddresspreference"; //internal const string ApplicationIntent = APPLICATIONINTENT; - internal const string APPLICATIONINTENT = "ApplicationIntent"; + internal const string APPLICATIONINTENT = "applicationintent"; //internal const string AttachDBFilename = EXTENDEDPROPERTIES+","+INITIALFILENAME; internal const string EXTENDEDPROPERTIES = "extended properties"; @@ -1083,10 +1081,10 @@ internal static class DbConnectionStringSynonyms internal const string TIMEOUT = "timeout"; //internal const string ConnectRetryCount = CONNECTRETRYCOUNT; - internal const string CONNECTRETRYCOUNT = "ConnectRetryCount"; + internal const string CONNECTRETRYCOUNT = "connectretrycount"; //internal const string ConnectRetryInterval = CONNECTRETRYINTERVAL; - internal const string CONNECTRETRYINTERVAL = "ConnectRetryInterval"; + internal const string CONNECTRETRYINTERVAL = "connectretryinterval"; //internal const string CurrentLanguage = LANGUAGE; internal const string LANGUAGE = "language"; @@ -1102,23 +1100,23 @@ internal static class DbConnectionStringSynonyms internal const string DATABASE = "database"; //internal const string IntegratedSecurity = TRUSTEDCONNECTION; - internal const string TRUSTEDCONNECTION = "trusted_connection"; // underscore introduced in Everett + internal const string TRUSTEDCONNECTION = "trusted_connection"; // underscore introduced in everett //internal const string LoadBalanceTimeout = ConnectionLifetime; internal const string ConnectionLifetime = "connection lifetime"; //internal const string MultipleActiveResultSets = MULTIPLEACTIVERESULTSETS; - internal const string MULTIPLEACTIVERESULTSETS = "MultipleActiveResultSets"; + internal const string MULTIPLEACTIVERESULTSETS = "multipleactiveresultsets"; //internal const string MultiSubnetFailover = MULTISUBNETFAILOVER; - internal const string MULTISUBNETFAILOVER = "MultiSubnetFailover"; + internal const string MULTISUBNETFAILOVER = "multisubnetfailover"; //internal const string NetworkLibrary = NET+","+NETWORK; internal const string NET = "net"; internal const string NETWORK = "network"; //internal const string PoolBlockingPeriod = POOLBLOCKINGPERIOD; - internal const string POOLBLOCKINGPERIOD = "PoolBlockingPeriod"; + internal const string POOLBLOCKINGPERIOD = "poolblockingperiod"; //internal const string Password = Pwd; internal const string Pwd = "pwd"; @@ -1127,7 +1125,7 @@ internal static class DbConnectionStringSynonyms internal const string PERSISTSECURITYINFO = "persistsecurityinfo"; //internal const string TrustServerCertificate = TRUSTSERVERCERTIFICATE; - internal const string TRUSTSERVERCERTIFICATE = "TrustServerCertificate"; + internal const string TRUSTSERVERCERTIFICATE = "trustservercertificate"; //internal const string UserID = UID+","+User; internal const string UID = "uid"; diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs index 25f591f1c2..d15e241f75 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/ActiveDirectoryAuthenticationProvider.cs @@ -33,10 +33,16 @@ private static ConcurrentDictionary - public ActiveDirectoryAuthenticationProvider() => new ActiveDirectoryAuthenticationProvider(DefaultDeviceFlowCallback); + public ActiveDirectoryAuthenticationProvider() + : this(DefaultDeviceFlowCallback) + { + } /// - public ActiveDirectoryAuthenticationProvider(string applicationClientId) => new ActiveDirectoryAuthenticationProvider(DefaultDeviceFlowCallback, applicationClientId); + public ActiveDirectoryAuthenticationProvider(string applicationClientId) + : this(DefaultDeviceFlowCallback, applicationClientId) + { + } /// public ActiveDirectoryAuthenticationProvider(Func deviceCodeFlowCallbackMethod, string applicationClientId = null) @@ -215,7 +221,7 @@ public override async Task AcquireTokenAsync(SqlAuthenti { // Fetch available accounts from 'app' instance System.Collections.Generic.IEnumerator accounts = (await app.GetAccountsAsync()).GetEnumerator(); - + IAccount account = default; if (accounts.MoveNext()) { @@ -343,7 +349,7 @@ private async Task AcquireTokenInteractiveDeviceFlowAsync( } } - private Task DefaultDeviceFlowCallback(DeviceCodeResult result) + private static Task DefaultDeviceFlowCallback(DeviceCodeResult result) { // This will print the message on the console which tells the user where to go sign-in using // a separate browser and the code to enter once they sign in. diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/SmiEventSink.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SmiEventSink.cs similarity index 83% rename from src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/SmiEventSink.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SmiEventSink.cs index 1c672da82c..a7de4b1947 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/SmiEventSink.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SmiEventSink.cs @@ -4,25 +4,25 @@ namespace Microsoft.Data.SqlClient.Server { - - // SqlEventSink is implemented by calling code. In all methods that accept - // a SqlEventSink directly the sink must be able to handle multiple callbacks - // without control returning from the original call. - - // Methods that do not accept SmiEventSync are (generally) ProcessEvent on - // the SmiEventStream methods returning a SmiEventStream and methods that - // are certain to never call to the server (most will, for in-proc back end). - - // Methods are commented with their corresponding TDS token - - // NOTE: Throwing from these methods will not usually produce the desired - // effect -- the managed to native boundary will eat any exceptions, - // and will cause a simple "Something bad happened" exception to be - // thrown in the native to managed boundary... + /// + /// SqlEventSink is implemented by calling code. In all methods that accept + /// a SqlEventSink directly the sink must be able to handle multiple callbacks + /// without control returning from the original call. + /// + /// Methods that do not accept SmiEventSync are (generally) ProcessEvent on + /// the SmiEventStream methods returning a SmiEventStream and methods that + /// are certain to never call to the server (most will, for in-proc back end). + /// + /// Methods are commented with their corresponding TDS token + /// + /// NOTE: Throwing from these methods will not usually produce the desired + /// effect -- the managed to native boundary will eat any exceptions, + /// and will cause a simple "Something bad happened" exception to be + /// thrown in the native to managed boundary... + /// internal abstract class SmiEventSink { - - #region Active methods +#if NETFRAMEWORK // Called at end of stream whether errors or no internal abstract void BatchCompleted(); @@ -80,10 +80,9 @@ internal virtual void RowAvailable(SmiTypedGetterSetter rowData) // Called when a transaction is started (ENVCHANGE token) internal abstract void TransactionStarted(long transactionId); - #endregion - #region OBSOLETE METHODS - #region OBSOLETED as of V200 but active in previous version +#region OBSOLETE METHODS +#region OBSOLETED as of V200 but active in previous version // Called zero or one time when output parameters are available (errors could prevent event from occuring) internal virtual void ParametersAvailable(SmiParameterMetaData[] metaData, ITypedGettersV3 paramValues) { @@ -108,9 +107,9 @@ internal virtual void RowAvailable(ITypedGettersV3 rowData) Microsoft.Data.Common.ADP.InternalError(Microsoft.Data.Common.ADP.InternalErrorCode.UnimplementedSMIMethod); } - #endregion +#endregion - #region OBSOLETED and never shipped (without ObsoleteAttribute) +#region OBSOLETED and never shipped (without ObsoleteAttribute) // Called when a new row arrives (ROW token) internal virtual void RowAvailable(ITypedGetters rowData) { @@ -123,8 +122,9 @@ internal virtual void RowAvailable(ITypedGetters rowData) Microsoft.Data.Common.ADP.InternalError(Microsoft.Data.Common.ADP.InternalErrorCode.UnimplementedSMIMethod); } - #endregion - #endregion +#endregion +#endregion + +#endif } } - diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SmiEventSink_Default.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SmiEventSink_Default.cs similarity index 64% rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SmiEventSink_Default.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SmiEventSink_Default.cs index 9b94b49c13..39f87beaae 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/SmiEventSink_Default.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SmiEventSink_Default.cs @@ -6,16 +6,29 @@ namespace Microsoft.Data.SqlClient.Server { - internal class SmiEventSink_Default : SmiEventSink + internal partial class SmiEventSink_Default : SmiEventSink { private SqlErrorCollection _errors; private SqlErrorCollection _warnings; + internal virtual string ServerVersion => null; + + internal SmiEventSink_Default() + { + } internal bool HasMessages { get { +#if NETFRAMEWORK + SmiEventSink_Default parent = (SmiEventSink_Default)_parent; + if (null != parent) + { + return parent.HasMessages; + } + else +#endif { bool result = (null != _errors || null != _warnings); return result; @@ -23,31 +36,43 @@ internal bool HasMessages } } - virtual internal string ServerVersion - { - get - { - return null; - } - } - - - protected virtual void DispatchMessages() + protected virtual void DispatchMessages( +#if NETFRAMEWORK + bool ignoreNonFatalMessages +#endif + ) { // virtual because we want a default implementation in the cases // where we don't have a connection to process stuff, but we want to // provide the connection the ability to fire info messages when it // hooks up. +#if NETFRAMEWORK + SmiEventSink_Default parent = (SmiEventSink_Default)_parent; + if (null != parent) { - SqlException errors = ProcessMessages(true); // ignore warnings, because there's no place to send them... + parent.DispatchMessages(ignoreNonFatalMessages); + } + else +#endif + { + SqlException errors = ProcessMessages(true +#if NETFRAMEWORK + , ignoreNonFatalMessages +#endif + ); // ignore warnings, because there's no place to send them... if (null != errors) { throw errors; } } + } - protected SqlException ProcessMessages(bool ignoreWarnings) + protected SqlException ProcessMessages(bool ignoreWarnings +#if NETFRAMEWORK + , bool ignoreNonFatalMessages +#endif + ) { SqlException result = null; SqlErrorCollection temp = null; // temp variable to store that which is being thrown - so that local copies can be deleted @@ -55,7 +80,24 @@ protected SqlException ProcessMessages(bool ignoreWarnings) if (null != _errors) { Debug.Assert(0 != _errors.Count, "empty error collection?"); // must be something in the collection - +#if NETFRAMEWORK + if (ignoreNonFatalMessages) + { + temp = new SqlErrorCollection(); + foreach (SqlError error in _errors) + { + if (error.Class >= TdsEnums.FATAL_ERROR_CLASS) + { + temp.Add(error); + } + } + if (temp.Count <= 0) + { + temp = null; + } + } + else +#endif { if (null != _warnings) { @@ -92,20 +134,16 @@ protected SqlException ProcessMessages(bool ignoreWarnings) return result; } - internal void ProcessMessagesAndThrow() { +#if NETFRAMEWORK + ProcessMessagesAndThrow(false); +#else if (HasMessages) { DispatchMessages(); } - } - - - - internal SmiEventSink_Default() - { +#endif } } } - diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/SmiEventSink_Default.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SmiEventSink_Default.netfx.cs similarity index 64% rename from src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/SmiEventSink_Default.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SmiEventSink_Default.netfx.cs index 663d042127..75d61f09ff 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/Server/SmiEventSink_Default.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SmiEventSink_Default.netfx.cs @@ -6,14 +6,9 @@ namespace Microsoft.Data.SqlClient.Server { - internal class SmiEventSink_Default : SmiEventSink + internal partial class SmiEventSink_Default : SmiEventSink { - private SmiEventSink _parent; // next level up, which we'll defer to if we don't need to handle the event. - - private SqlErrorCollection _errors; - private SqlErrorCollection _warnings; - private SqlErrorCollection Errors { get @@ -27,41 +22,10 @@ private SqlErrorCollection Errors } } - internal bool HasMessages - { - get - { - SmiEventSink_Default parent = (SmiEventSink_Default)_parent; - if (null != parent) - { - return parent.HasMessages; - } - else - { - bool result = (null != _errors || null != _warnings); - return result; - } - } - } - - virtual internal string ServerVersion - { - get - { - return null; - } - } - internal SmiEventSink Parent { - get - { - return _parent; - } - set - { - _parent = value; - } + get => _parent; + set => _parent = value; } private SqlErrorCollection Warnings @@ -77,86 +41,12 @@ private SqlErrorCollection Warnings } } - protected virtual void DispatchMessages(bool ignoreNonFatalMessages) - { - // virtual because we want a default implementation in the cases - // where we don't have a connection to process stuff, but we want to - // provide the connection the ability to fire info messages when it - // hooks up. - SmiEventSink_Default parent = (SmiEventSink_Default)_parent; - if (null != parent) - { - parent.DispatchMessages(ignoreNonFatalMessages); - } - else - { - SqlException errors = ProcessMessages(true, ignoreNonFatalMessages); // ignore warnings, because there's no place to send them... - if (null != errors) - { - throw errors; - } - } - } - - protected SqlException ProcessMessages(bool ignoreWarnings, bool ignoreNonFatalMessages) + internal void ProcessMessagesAndThrow(bool ignoreNonFatalMessages) { - SqlException result = null; - SqlErrorCollection temp = null; // temp variable to store that which is being thrown - so that local copies can be deleted - - if (null != _errors) - { - Debug.Assert(0 != _errors.Count, "empty error collection?"); // must be something in the collection - - if (ignoreNonFatalMessages) - { - temp = new SqlErrorCollection(); - foreach (SqlError error in _errors) - { - if (error.Class >= TdsEnums.FATAL_ERROR_CLASS) - { - temp.Add(error); - } - } - if (temp.Count <= 0) - { - temp = null; - } - } - else - { - if (null != _warnings) - { - // When we throw an exception we place all the warnings that - // occurred at the end of the collection - after all the errors. - // That way the user can see all the errors AND warnings that - // occurred for the exception. - foreach (SqlError warning in _warnings) - { - _errors.Add(warning); - } - } - temp = _errors; - } - - _errors = null; - _warnings = null; - } - else - { - Debug.Assert(null == _warnings || 0 != _warnings.Count, "empty warning collection?");// must be something in the collection - - if (!ignoreWarnings) - { - temp = _warnings; - } - _warnings = null; - } - - if (null != temp) + if (HasMessages) { - result = SqlException.CreateException(temp, ServerVersion); + DispatchMessages(ignoreNonFatalMessages); } - return result; } internal void CleanMessages() @@ -173,19 +63,6 @@ internal void CleanMessages() } } - internal void ProcessMessagesAndThrow() - { - ProcessMessagesAndThrow(false); - } - - internal void ProcessMessagesAndThrow(bool ignoreNonFatalMessages) - { - if (HasMessages) - { - DispatchMessages(ignoreNonFatalMessages); - } - } - internal enum UnexpectedEventType { BatchCompleted, @@ -206,25 +83,19 @@ internal enum UnexpectedEventType TransactionStarted, } - - internal SmiEventSink_Default() - { - } - internal SmiEventSink_Default(SmiEventSink parent) { _parent = parent; } - - // NOTE: See the note in SmiEventSink about throwing from these methods; - // We're throwing here because we don't want to miss something, but - // you'll need to turn on Bid tracing to figure out what it is that - // was thrown, because they will be eaten by the server and replaced - // with a different exception. - - + // + //NOTE: See the note in SmiEventSink about throwing from these methods; + // We're throwing here because we don't want to miss something, but + //you'll need to turn on Bid tracing to figure out what it is that + //was thrown, because they will be eaten by the server and replaced + //with a different exception. // Called at end of stream + // internal override void BatchCompleted() { if (null == _parent) diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlDataRecord.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlDataRecord.cs new file mode 100644 index 0000000000..9f5c11f60c --- /dev/null +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlDataRecord.cs @@ -0,0 +1,422 @@ +// 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.Data; +using System.Data.SqlTypes; +using Microsoft.Data.Common; +using Microsoft.Data.ProviderBase; + +namespace Microsoft.Data.SqlClient.Server +{ + /// + public partial class SqlDataRecord : IDataRecord + { + private readonly SmiRecordBuffer _recordBuffer; + private readonly SmiExtendedMetaData[] _columnSmiMetaData; + private readonly SmiEventSink_Default _eventSink; + private readonly SqlMetaData[] _columnMetaData; + private FieldNameLookup _fieldNameLookup; + private readonly bool _usesStringStorageForXml = false; + + private static readonly SmiMetaData s_maxNVarCharForXml = new SmiMetaData( + SqlDbType.NVarChar, + SmiMetaData.UnlimitedMaxLengthIndicator, + SmiMetaData.DefaultNVarChar_NoCollation.Precision, + SmiMetaData.DefaultNVarChar_NoCollation.Scale, + SmiMetaData.DefaultNVarChar.LocaleId, + SmiMetaData.DefaultNVarChar.CompareOptions, + userDefinedType: null + ); + + /// + public virtual int FieldCount => _columnMetaData.Length; + + /// + public virtual string GetName(int ordinal) => GetSqlMetaData(ordinal).Name; + + /// + public virtual string GetDataTypeName(int ordinal) + { + SqlMetaData metaData = GetSqlMetaData(ordinal); + if (metaData.SqlDbType == SqlDbType.Udt) + { + return metaData.UdtTypeName; + } + else + { + return MetaType.GetMetaTypeFromSqlDbType(metaData.SqlDbType, false).TypeName; + } + } + + /// + public virtual Type GetFieldType(int ordinal) => GetFieldTypeFrameworkSpecific(ordinal); + + /// + public virtual object GetValue(int ordinal) => GetValueFrameworkSpecific(ordinal); + + /// + public virtual int GetValues(object[] values) + { + if (values == null) + { + throw ADP.ArgumentNull(nameof(values)); + } + + int copyLength = (values.Length < FieldCount) ? values.Length : FieldCount; + for (int i = 0; i < copyLength; i++) + { + values[i] = GetValue(i); + } + + return copyLength; + } + + /// + public virtual int GetOrdinal(string name) + { + if (_fieldNameLookup == null) + { + string[] names = new string[FieldCount]; + for (int i = 0; i < names.Length; i++) + { + names[i] = GetSqlMetaData(i).Name; + } + + _fieldNameLookup = new FieldNameLookup(names, -1); + } + + return _fieldNameLookup.GetOrdinal(name); + } + + /// + public virtual object this[int ordinal] => GetValue(ordinal); + + /// + public virtual object this[string name] => GetValue(GetOrdinal(name)); + + /// + public virtual bool GetBoolean(int ordinal) => ValueUtilsSmi.GetBoolean(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual byte GetByte(int ordinal) => ValueUtilsSmi.GetByte(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual long GetBytes(int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length) => ValueUtilsSmi.GetBytes(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), fieldOffset, buffer, bufferOffset, length, throwOnNull: true); + + /// + public virtual char GetChar(int ordinal) => throw ADP.NotSupported(); + + /// + public virtual long GetChars(int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length) => ValueUtilsSmi.GetChars(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), fieldOffset, buffer, bufferOffset, length); + + /// + public virtual Guid GetGuid(int ordinal) => ValueUtilsSmi.GetGuid(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual short GetInt16(int ordinal) => ValueUtilsSmi.GetInt16(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual int GetInt32(int ordinal) => ValueUtilsSmi.GetInt32(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual long GetInt64(int ordinal) => ValueUtilsSmi.GetInt64(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual float GetFloat(int ordinal) => ValueUtilsSmi.GetSingle(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual double GetDouble(int ordinal) => ValueUtilsSmi.GetDouble(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual string GetString(int ordinal) + { + SmiMetaData colMeta = GetSmiMetaData(ordinal); + if (_usesStringStorageForXml && colMeta.SqlDbType == SqlDbType.Xml) + { + return ValueUtilsSmi.GetString(_eventSink, _recordBuffer, ordinal, s_maxNVarCharForXml); + } + else + { + return ValueUtilsSmi.GetString(_eventSink, _recordBuffer, ordinal, colMeta); + } + } + + /// + public virtual decimal GetDecimal(int ordinal) => ValueUtilsSmi.GetDecimal(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual DateTime GetDateTime(int ordinal) => ValueUtilsSmi.GetDateTime(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual DateTimeOffset GetDateTimeOffset(int ordinal) => ValueUtilsSmi.GetDateTimeOffset(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual TimeSpan GetTimeSpan(int ordinal) => ValueUtilsSmi.GetTimeSpan(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual bool IsDBNull(int ordinal) + { + ThrowIfInvalidOrdinal(ordinal); + return ValueUtilsSmi.IsDBNull(_eventSink, _recordBuffer, ordinal); + } + + /// + // ISqlRecord implementation + public virtual SqlMetaData GetSqlMetaData(int ordinal) + { + ThrowIfInvalidOrdinal(ordinal); + return _columnMetaData[ordinal]; + } + + /// + public virtual Type GetSqlFieldType(int ordinal) => MetaType.GetMetaTypeFromSqlDbType(GetSqlMetaData(ordinal).SqlDbType, false).SqlType; + + /// + public virtual object GetSqlValue(int ordinal) => GetSqlValueFrameworkSpecific(ordinal); + + /// + public virtual int GetSqlValues(object[] values) + { + if (null == values) + { + throw ADP.ArgumentNull(nameof(values)); + } + + int copyLength = (values.Length < FieldCount) ? values.Length : FieldCount; + for (int i = 0; i < copyLength; i++) + { + values[i] = GetSqlValue(i); + } + + return copyLength; + } + + /// + public virtual SqlBinary GetSqlBinary(int ordinal) => ValueUtilsSmi.GetSqlBinary(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual SqlBytes GetSqlBytes(int ordinal) => GetSqlBytesFrameworkSpecific(ordinal); + + /// + public virtual SqlXml GetSqlXml(int ordinal) => GetSqlXmlFrameworkSpecific(ordinal); + + /// + public virtual SqlBoolean GetSqlBoolean(int ordinal) => ValueUtilsSmi.GetSqlBoolean(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual SqlByte GetSqlByte(int ordinal) => ValueUtilsSmi.GetSqlByte(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual SqlChars GetSqlChars(int ordinal) => GetSqlCharsFrameworkSpecific(ordinal); + + /// + public virtual SqlInt16 GetSqlInt16(int ordinal) => ValueUtilsSmi.GetSqlInt16(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual SqlInt32 GetSqlInt32(int ordinal) => ValueUtilsSmi.GetSqlInt32(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual SqlInt64 GetSqlInt64(int ordinal) => ValueUtilsSmi.GetSqlInt64(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual SqlSingle GetSqlSingle(int ordinal) => ValueUtilsSmi.GetSqlSingle(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual SqlDouble GetSqlDouble(int ordinal) => ValueUtilsSmi.GetSqlDouble(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual SqlMoney GetSqlMoney(int ordinal) => ValueUtilsSmi.GetSqlMoney(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual SqlDateTime GetSqlDateTime(int ordinal) => ValueUtilsSmi.GetSqlDateTime(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual SqlDecimal GetSqlDecimal(int ordinal) => ValueUtilsSmi.GetSqlDecimal(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual SqlString GetSqlString(int ordinal) => ValueUtilsSmi.GetSqlString(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + public virtual SqlGuid GetSqlGuid(int ordinal) => ValueUtilsSmi.GetSqlGuid(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + /// + // ISqlUpdateableRecord Implementation + public virtual int SetValues(params object[] values) => SetValuesFrameworkSpecific(values); + + /// + public virtual void SetValue(int ordinal, object value) => SetValueFrameworkSpecific(ordinal, value); + + /// + public virtual void SetBoolean(int ordinal, bool value) => ValueUtilsSmi.SetBoolean(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetByte(int ordinal, byte value) => ValueUtilsSmi.SetByte(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetBytes(int ordinal, long fieldOffset, byte[] buffer, int bufferOffset, int length) => ValueUtilsSmi.SetBytes(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), fieldOffset, buffer, bufferOffset, length); + + /// + public virtual void SetChar(int ordinal, char value) => throw ADP.NotSupported(); + + /// + public virtual void SetChars(int ordinal, long fieldOffset, char[] buffer, int bufferOffset, int length) => ValueUtilsSmi.SetChars(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), fieldOffset, buffer, bufferOffset, length); + + /// + public virtual void SetInt16(int ordinal, short value) => ValueUtilsSmi.SetInt16(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetInt32(int ordinal, int value) => ValueUtilsSmi.SetInt32(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetInt64(int ordinal, long value) => ValueUtilsSmi.SetInt64(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetFloat(int ordinal, float value) => ValueUtilsSmi.SetSingle(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + /// + public virtual void SetDouble(int ordinal, double value) => ValueUtilsSmi.SetDouble(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetString(int ordinal, string value) => ValueUtilsSmi.SetString(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetDecimal(int ordinal, decimal value) => ValueUtilsSmi.SetDecimal(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetDateTime(int ordinal, DateTime value) => ValueUtilsSmi.SetDateTime(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetTimeSpan(int ordinal, TimeSpan value) => SetTimeSpanFrameworkSpecific(ordinal, value); + + /// + public virtual void SetDateTimeOffset(int ordinal, DateTimeOffset value) => SetDateTimeOffsetFrameworkSpecific(ordinal, value); + + /// + public virtual void SetDBNull(int ordinal) + { + ThrowIfInvalidOrdinal(ordinal); + ValueUtilsSmi.SetDBNull(_eventSink, _recordBuffer, ordinal, true); + } + + /// + public virtual void SetGuid(int ordinal, Guid value) => ValueUtilsSmi.SetGuid(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetSqlBoolean(int ordinal, SqlBoolean value) => ValueUtilsSmi.SetSqlBoolean(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetSqlByte(int ordinal, SqlByte value) => ValueUtilsSmi.SetSqlByte(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetSqlInt16(int ordinal, SqlInt16 value) => ValueUtilsSmi.SetSqlInt16(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetSqlInt32(int ordinal, SqlInt32 value) => ValueUtilsSmi.SetSqlInt32(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetSqlInt64(int ordinal, SqlInt64 value) => ValueUtilsSmi.SetSqlInt64(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetSqlSingle(int ordinal, SqlSingle value) => ValueUtilsSmi.SetSqlSingle(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetSqlDouble(int ordinal, SqlDouble value) => ValueUtilsSmi.SetSqlDouble(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetSqlMoney(int ordinal, SqlMoney value) => ValueUtilsSmi.SetSqlMoney(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetSqlDateTime(int ordinal, SqlDateTime value) => ValueUtilsSmi.SetSqlDateTime(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetSqlXml(int ordinal, SqlXml value) => ValueUtilsSmi.SetSqlXml(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetSqlDecimal(int ordinal, SqlDecimal value) => ValueUtilsSmi.SetSqlDecimal(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetSqlString(int ordinal, SqlString value) => ValueUtilsSmi.SetSqlString(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetSqlBinary(int ordinal, SqlBinary value) => ValueUtilsSmi.SetSqlBinary(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetSqlGuid(int ordinal, SqlGuid value) => ValueUtilsSmi.SetSqlGuid(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetSqlChars(int ordinal, SqlChars value) => ValueUtilsSmi.SetSqlChars(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + /// + public virtual void SetSqlBytes(int ordinal, SqlBytes value) => ValueUtilsSmi.SetSqlBytes(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + // SqlDataRecord public API + /// + public SqlDataRecord(params SqlMetaData[] metaData) + { + // Initial consistency check + if (metaData == null) + { + throw ADP.ArgumentNull(nameof(metaData)); + } + + _columnMetaData = new SqlMetaData[metaData.Length]; + _columnSmiMetaData = new SmiExtendedMetaData[metaData.Length]; +#if NETFRAMEWORK + ulong smiVersion = SmiVersion; +#endif + for (int i = 0; i < _columnSmiMetaData.Length; i++) + { + if (metaData[i] == null) + { + throw ADP.ArgumentNull($"{nameof(metaData)}[{i}]"); + } + _columnMetaData[i] = metaData[i]; + _columnSmiMetaData[i] = MetaDataUtilsSmi.SqlMetaDataToSmiExtendedMetaData(_columnMetaData[i]); +#if NETFRAMEWORK + if (!MetaDataUtilsSmi.IsValidForSmiVersion(_columnSmiMetaData[i], smiVersion)) + { + throw ADP.VersionDoesNotSupportDataType(_columnSmiMetaData[i].TypeName); + } +#endif + } + + _eventSink = new SmiEventSink_Default(); +#if NETFRAMEWORK + if (InOutOfProcHelper.InProc) + { + _recordContext = SmiContextFactory.Instance.GetCurrentContext(); + _recordBuffer = _recordContext.CreateRecordBuffer(_columnSmiMetaData, _eventSink); + _usesStringStorageForXml = false; + } + else + { + _recordContext = null; + _recordBuffer = new MemoryRecordBuffer(_columnSmiMetaData); + _usesStringStorageForXml = true; + } +#else + _recordBuffer = new MemoryRecordBuffer(_columnSmiMetaData); + _eventSink.ProcessMessagesAndThrow(); +#endif + } + + internal SmiExtendedMetaData GetSmiMetaData(int ordinal) + { + ThrowIfInvalidOrdinal(ordinal); + return _columnSmiMetaData[ordinal]; + } + + internal void ThrowIfInvalidOrdinal(int ordinal) + { + if (0 > ordinal || FieldCount <= ordinal) + { + throw ADP.IndexOutOfRange(ordinal); + } + } + + /// + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + IDataReader System.Data.IDataRecord.GetData(int ordinal) => throw ADP.NotSupported(); + } +} diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlDataRecord.netcore.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlDataRecord.netcore.cs new file mode 100644 index 0000000000..106d9f6b0a --- /dev/null +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlDataRecord.netcore.cs @@ -0,0 +1,93 @@ +// 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.Data; +using System.Data.SqlTypes; +using Microsoft.Data.Common; + +namespace Microsoft.Data.SqlClient.Server +{ + /// + public partial class SqlDataRecord : IDataRecord + { + private Type GetFieldTypeFrameworkSpecific(int ordinal) + => MetaType.GetMetaTypeFromSqlDbType(GetSqlMetaData(ordinal).SqlDbType, false).ClassType; + + private object GetValueFrameworkSpecific(int ordinal) + => ValueUtilsSmi.GetValue200(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + private object GetSqlValueFrameworkSpecific(int ordinal) + => ValueUtilsSmi.GetSqlValue200(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + private SqlBytes GetSqlBytesFrameworkSpecific(int ordinal) + => ValueUtilsSmi.GetSqlBytes(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + private SqlXml GetSqlXmlFrameworkSpecific(int ordinal) + => ValueUtilsSmi.GetSqlXml(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + + private SqlChars GetSqlCharsFrameworkSpecific(int ordinal) + => ValueUtilsSmi.GetSqlChars(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal)); + private int SetValuesFrameworkSpecific(params object[] values) + { + if (values == null) + { + throw ADP.ArgumentNull(nameof(values)); + } + + // Allow values array longer than FieldCount, just ignore the extra cells. + int copyLength = (values.Length > FieldCount) ? FieldCount : values.Length; + + ExtendedClrTypeCode[] typeCodes = new ExtendedClrTypeCode[copyLength]; + + // Verify all data values as acceptable before changing current state. + for (int i = 0; i < copyLength; i++) + { + SqlMetaData metaData = GetSqlMetaData(i); + typeCodes[i] = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType( + metaData.SqlDbType, + isMultiValued: false, + values[i], + metaData.Type + ); + if (typeCodes[i] == ExtendedClrTypeCode.Invalid) + { + throw ADP.InvalidCast(); + } + } + + // Now move the data (it'll only throw if someone plays with the values array between + // the validation loop and here, or if an invalid UDT was sent). + for (int i = 0; i < copyLength; i++) + { + ValueUtilsSmi.SetCompatibleValueV200(_eventSink, _recordBuffer, i, GetSmiMetaData(i), values[i], typeCodes[i], offset: 0, length: 0, peekAhead: null); + } + + return copyLength; + } + + private void SetValueFrameworkSpecific(int ordinal, object value) + { + SqlMetaData metaData = GetSqlMetaData(ordinal); + ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType( + metaData.SqlDbType, + isMultiValued: false, + value, + metaData.Type + ); + if (typeCode == ExtendedClrTypeCode.Invalid) + { + throw ADP.InvalidCast(); + } + + ValueUtilsSmi.SetCompatibleValueV200(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value, typeCode, offset: 0, length: 0, peekAhead: null); + } + + private void SetTimeSpanFrameworkSpecific(int ordinal, TimeSpan value) + => ValueUtilsSmi.SetTimeSpan(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + private void SetDateTimeOffsetFrameworkSpecific(int ordinal, DateTimeOffset value) + => ValueUtilsSmi.SetDateTimeOffset(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value); + + } +} diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlDataRecord.netfx.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlDataRecord.netfx.cs new file mode 100644 index 0000000000..8d65b63921 --- /dev/null +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/SqlDataRecord.netfx.cs @@ -0,0 +1,135 @@ +// 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.Data; +using System.Data.SqlTypes; +using Microsoft.Data.Common; + +namespace Microsoft.Data.SqlClient.Server +{ + /// + public partial class SqlDataRecord : IDataRecord + { + private readonly SmiContext _recordContext; + + private Type GetFieldTypeFrameworkSpecific(int ordinal) + { + SqlMetaData md = GetSqlMetaData(ordinal); + if (md.SqlDbType == SqlDbType.Udt) + { + return md.Type; + } + else + { + return MetaType.GetMetaTypeFromSqlDbType(md.SqlDbType, false).ClassType; + } + } + + private object GetValueFrameworkSpecific(int ordinal) + { + SmiMetaData metaData = GetSmiMetaData(ordinal); + if (SmiVersion >= SmiContextFactory.KatmaiVersion) + { + return ValueUtilsSmi.GetValue200(_eventSink, _recordBuffer, ordinal, metaData, _recordContext); + } + else + { + return ValueUtilsSmi.GetValue(_eventSink, _recordBuffer, ordinal, metaData, _recordContext); + } + } + + private object GetSqlValueFrameworkSpecific(int ordinal) + { + SmiMetaData metaData = GetSmiMetaData(ordinal); + if (SmiVersion >= SmiContextFactory.KatmaiVersion) + { + return ValueUtilsSmi.GetSqlValue200(_eventSink, _recordBuffer, ordinal, metaData, _recordContext); + } + return ValueUtilsSmi.GetSqlValue(_eventSink, _recordBuffer, ordinal, metaData, _recordContext); + } + + private SqlBytes GetSqlBytesFrameworkSpecific(int ordinal) => ValueUtilsSmi.GetSqlBytes(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), _recordContext); + + private SqlXml GetSqlXmlFrameworkSpecific(int ordinal) => ValueUtilsSmi.GetSqlXml(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), _recordContext); + + private SqlChars GetSqlCharsFrameworkSpecific(int ordinal) => ValueUtilsSmi.GetSqlChars(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), _recordContext); + + private int SetValuesFrameworkSpecific(params object[] values) + { + if (values == null) + { + throw ADP.ArgumentNull(nameof(values)); + } + + // Allow values array longer than FieldCount, just ignore the extra cells. + int copyLength = (values.Length > FieldCount) ? FieldCount : values.Length; + + ExtendedClrTypeCode[] typeCodes = new ExtendedClrTypeCode[copyLength]; + + // Verify all data values as acceptable before changing current state. + for (int i = 0; i < copyLength; i++) + { + SqlMetaData metaData = GetSqlMetaData(i); + typeCodes[i] = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType( + metaData.SqlDbType, + isMultiValued: false, + values[i], + metaData.Type, + SmiVersion + ); + if (typeCodes[i] == ExtendedClrTypeCode.Invalid) + { + throw ADP.InvalidCast(); + } + } + + // Now move the data (it'll only throw if someone plays with the values array between + // the validation loop and here, or if an invalid UDT was sent). + for (int i = 0; i < copyLength; i++) + { + if (SmiVersion >= SmiContextFactory.KatmaiVersion) + { + ValueUtilsSmi.SetCompatibleValueV200(_eventSink, _recordBuffer, i, GetSmiMetaData(i), values[i], typeCodes[i], offset: 0, length: 0, peekAhead: null); + } + else + { + ValueUtilsSmi.SetCompatibleValue(_eventSink, _recordBuffer, i, GetSmiMetaData(i), values[i], typeCodes[i], offset: 0); + } + } + + return copyLength; + } + + private void SetValueFrameworkSpecific(int ordinal, object value) + { + SqlMetaData metaData = GetSqlMetaData(ordinal); + ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType( + metaData.SqlDbType, + isMultiValued: false, + value, + metaData.Type, + SmiVersion + ); + if (typeCode == ExtendedClrTypeCode.Invalid) + { + throw ADP.InvalidCast(); + } + + if (SmiVersion >= SmiContextFactory.KatmaiVersion) + { + ValueUtilsSmi.SetCompatibleValueV200(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value, typeCode, offset: 0, length: 0, peekAhead: null); + } + else + { + ValueUtilsSmi.SetCompatibleValue(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value, typeCode, offset: 0); + } + } + + private void SetTimeSpanFrameworkSpecific(int ordinal, TimeSpan value) => ValueUtilsSmi.SetTimeSpan(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value, SmiVersion >= SmiContextFactory.KatmaiVersion); + private void SetDateTimeOffsetFrameworkSpecific(int ordinal, DateTimeOffset value) => ValueUtilsSmi.SetDateTimeOffset(_eventSink, _recordBuffer, ordinal, GetSmiMetaData(ordinal), value, SmiVersion >= SmiContextFactory.KatmaiVersion); + + private ulong SmiVersion => InOutOfProcHelper.InProc ? SmiContextFactory.Instance.NegotiatedSmiVersion : SmiContextFactory.LatestVersion; + } +} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs similarity index 86% rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs index cdf0802ef3..f53396cdaa 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.cs @@ -23,7 +23,7 @@ namespace Microsoft.Data.SqlClient.Server // // These are all based off of knowing the clr type of the value // as an ExtendedClrTypeCode enum for rapid access (lookup in static array is best, if possible). - internal static class ValueUtilsSmi + internal static partial class ValueUtilsSmi { private const int __maxByteChunkSize = TdsEnums.MAXSIZE; private const int __maxCharChunkSize = TdsEnums.MAXSIZE / sizeof(char); @@ -60,7 +60,11 @@ internal static bool GetBoolean(SmiEventSink_Default sink, ITypedGettersV3 gette return GetBoolean_Unchecked(sink, getters, ordinal); } - object result = GetValue(sink, getters, ordinal, metaData); + object result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -75,7 +79,11 @@ internal static byte GetByte(SmiEventSink_Default sink, ITypedGettersV3 getters, { return GetByte_Unchecked(sink, getters, ordinal); } - object result = GetValue(sink, getters, ordinal, metaData); + object result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -85,7 +93,11 @@ internal static byte GetByte(SmiEventSink_Default sink, ITypedGettersV3 getters, private static long GetBytesConversion(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, long fieldOffset, byte[] buffer, int bufferOffset, int length, bool throwOnNull) { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -197,7 +209,11 @@ internal static long GetChars(SmiEventSink_Default sink, ITypedGettersV3 getters return length; } - string value = ((string)GetValue(sink, getters, ordinal, metaData)); + string value = ((string)GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + )); if (null == value) { throw ADP.InvalidCast(); @@ -219,7 +235,11 @@ internal static DateTime GetDateTime(SmiEventSink_Default sink, ITypedGettersV3 { return GetDateTime_Unchecked(sink, getters, ordinal); } - object result = GetValue(sink, getters, ordinal, metaData); + object result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -235,7 +255,11 @@ internal static DateTimeOffset GetDateTimeOffset(SmiEventSink_Default sink, ITyp return GetDateTimeOffset(sink, (SmiTypedGetterSetter)getters, ordinal, metaData); } ThrowIfITypedGettersIsNull(sink, getters, ordinal); - object result = GetValue(sink, getters, ordinal, metaData); + object result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -251,7 +275,11 @@ internal static DateTimeOffset GetDateTimeOffset(SmiEventSink_Default sink, SmiT { return GetDateTimeOffset_Unchecked(sink, getters, ordinal); } - return (DateTimeOffset)GetValue200(sink, getters, ordinal, metaData); + return (DateTimeOffset)GetValue200(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); } internal static decimal GetDecimal(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) @@ -261,7 +289,11 @@ internal static decimal GetDecimal(SmiEventSink_Default sink, ITypedGettersV3 ge { return GetDecimal_PossiblyMoney(sink, getters, ordinal, metaData); } - object result = GetValue(sink, getters, ordinal, metaData); + object result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -276,7 +308,11 @@ internal static double GetDouble(SmiEventSink_Default sink, ITypedGettersV3 gett { return GetDouble_Unchecked(sink, getters, ordinal); } - object result = GetValue(sink, getters, ordinal, metaData); + object result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -291,7 +327,11 @@ internal static Guid GetGuid(SmiEventSink_Default sink, ITypedGettersV3 getters, { return GetGuid_Unchecked(sink, getters, ordinal); } - object result = GetValue(sink, getters, ordinal, metaData); + object result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -306,7 +346,11 @@ internal static short GetInt16(SmiEventSink_Default sink, ITypedGettersV3 getter { return GetInt16_Unchecked(sink, getters, ordinal); } - object obj = GetValue(sink, getters, ordinal, metaData); + object obj = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -321,7 +365,11 @@ internal static int GetInt32(SmiEventSink_Default sink, ITypedGettersV3 getters, { return GetInt32_Unchecked(sink, getters, ordinal); } - object result = GetValue(sink, getters, ordinal, metaData); + object result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -336,7 +384,11 @@ internal static long GetInt64(SmiEventSink_Default sink, ITypedGettersV3 getters { return GetInt64_Unchecked(sink, getters, ordinal); } - object result = GetValue(sink, getters, ordinal, metaData); + object result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -351,7 +403,11 @@ internal static float GetSingle(SmiEventSink_Default sink, ITypedGettersV3 gette { return GetSingle_Unchecked(sink, getters, ordinal); } - object result = GetValue(sink, getters, ordinal, metaData); + object result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -369,7 +425,11 @@ internal static SqlBinary GetSqlBinary(SmiEventSink_Default sink, ITypedGettersV } return GetSqlBinary_Unchecked(sink, getters, ordinal); } - object result = GetSqlValue(sink, getters, ordinal, metaData); + object result = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -387,7 +447,11 @@ internal static SqlBoolean GetSqlBoolean(SmiEventSink_Default sink, ITypedGetter } return new SqlBoolean(GetBoolean_Unchecked(sink, getters, ordinal)); } - object result = GetSqlValue(sink, getters, ordinal, metaData); + object result = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -405,7 +469,11 @@ internal static SqlByte GetSqlByte(SmiEventSink_Default sink, ITypedGettersV3 ge } return new SqlByte(GetByte_Unchecked(sink, getters, ordinal)); } - object result = GetSqlValue(sink, getters, ordinal, metaData); + object result = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == result) { throw ADP.InvalidCast(); @@ -413,7 +481,11 @@ internal static SqlByte GetSqlByte(SmiEventSink_Default sink, ITypedGettersV3 ge return (SqlByte)result; } - internal static SqlBytes GetSqlBytes(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) + internal static SqlBytes GetSqlBytes(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData +#if NETFRAMEWORK + , SmiContext context +#endif + ) { SqlBytes result; if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlBytes)) @@ -433,14 +505,22 @@ internal static SqlBytes GetSqlBytes(SmiEventSink_Default sink, ITypedGettersV3 else { Stream s = new SmiGettersStream(sink, getters, ordinal, metaData); - s = CopyIntoNewSmiScratchStream(s, sink); + s = CopyIntoNewSmiScratchStream(s, sink +#if NETFRAMEWORK + , context +#endif + ); result = new SqlBytes(s); } } } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -459,7 +539,11 @@ internal static SqlBytes GetSqlBytes(SmiEventSink_Default sink, ITypedGettersV3 return result; } - internal static SqlChars GetSqlChars(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) + internal static SqlChars GetSqlChars(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData +#if NETFRAMEWORK + , SmiContext context +#endif + ) { SqlChars result; if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlChars)) @@ -470,8 +554,28 @@ internal static SqlChars GetSqlChars(SmiEventSink_Default sink, ITypedGettersV3 } else { +#if NETFRAMEWORK + long length = GetCharsLength_Unchecked(sink, getters, ordinal); + if (length < __maxCharChunkSize || !InOutOfProcHelper.InProc) + { + char[] charBuffer = GetCharArray_Unchecked(sink, getters, ordinal); + result = new SqlChars(charBuffer); + } + else + { // InProc only + Stream s = new SmiGettersStream(sink, getters, ordinal, metaData); + SqlStreamChars sc = CopyIntoNewSmiScratchStreamChars(s, sink, context); + + Type SqlCharsType = (typeof(SqlChars)); + Type[] argTypes = new Type[] { typeof(SqlStreamChars) }; + SqlChars SqlCharsInstance = (SqlChars)SqlCharsType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, + null, argTypes, null).Invoke(new object[] { sc }); + result = SqlCharsInstance; + } +#else char[] charBuffer = GetCharArray_Unchecked(sink, getters, ordinal); result = new SqlChars(charBuffer); +#endif } } else @@ -479,7 +583,11 @@ internal static SqlChars GetSqlChars(SmiEventSink_Default sink, ITypedGettersV3 SqlString stringValue; if (SqlDbType.Xml == metaData.SqlDbType) { - SqlXml xmlValue = GetSqlXml_Unchecked(sink, getters, ordinal); + SqlXml xmlValue = GetSqlXml_Unchecked(sink, getters, ordinal +#if NETFRAMEWORK + , null +#endif + ); if (xmlValue.IsNull) { @@ -492,7 +600,11 @@ internal static SqlChars GetSqlChars(SmiEventSink_Default sink, ITypedGettersV3 } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -530,7 +642,11 @@ internal static SqlDateTime GetSqlDateTime(SmiEventSink_Default sink, ITypedGett } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -557,7 +673,11 @@ internal static SqlDecimal GetSqlDecimal(SmiEventSink_Default sink, ITypedGetter } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -585,7 +705,11 @@ internal static SqlDouble GetSqlDouble(SmiEventSink_Default sink, ITypedGettersV } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -613,7 +737,11 @@ internal static SqlGuid GetSqlGuid(SmiEventSink_Default sink, ITypedGettersV3 ge } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -641,7 +769,11 @@ internal static SqlInt16 GetSqlInt16(SmiEventSink_Default sink, ITypedGettersV3 } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -669,7 +801,11 @@ internal static SqlInt32 GetSqlInt32(SmiEventSink_Default sink, ITypedGettersV3 } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -696,7 +832,11 @@ internal static SqlInt64 GetSqlInt64(SmiEventSink_Default sink, ITypedGettersV3 } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -723,7 +863,11 @@ internal static SqlMoney GetSqlMoney(SmiEventSink_Default sink, ITypedGettersV3 } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -751,7 +895,11 @@ internal static SqlSingle GetSqlSingle(SmiEventSink_Default sink, ITypedGettersV } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -779,7 +927,11 @@ internal static SqlString GetSqlString(SmiEventSink_Default sink, ITypedGettersV } else if (SqlDbType.Xml == metaData.SqlDbType) { - SqlXml xmlValue = GetSqlXml_Unchecked(sink, getters, ordinal); + SqlXml xmlValue = GetSqlXml_Unchecked(sink, getters, ordinal +#if NETFRAMEWORK + , null +#endif + ); if (xmlValue.IsNull) { @@ -792,7 +944,11 @@ internal static SqlString GetSqlString(SmiEventSink_Default sink, ITypedGettersV } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -803,7 +959,11 @@ internal static SqlString GetSqlString(SmiEventSink_Default sink, ITypedGettersV return result; } - internal static SqlXml GetSqlXml(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) + internal static SqlXml GetSqlXml(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData +#if NETFRAMEWORK + , SmiContext context +#endif + ) { SqlXml result; if (CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.SqlXml)) @@ -814,12 +974,20 @@ internal static SqlXml GetSqlXml(SmiEventSink_Default sink, ITypedGettersV3 gett } else { - result = GetSqlXml_Unchecked(sink, getters, ordinal); + result = GetSqlXml_Unchecked(sink, getters, ordinal +#if NETFRAMEWORK + , context +#endif + ); } } else { - object obj = GetSqlValue(sink, getters, ordinal, metaData); + object obj = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -837,7 +1005,11 @@ internal static string GetString(SmiEventSink_Default sink, ITypedGettersV3 gett { return GetString_Unchecked(sink, getters, ordinal); } - object obj = GetValue(sink, getters, ordinal, metaData); + object obj = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); if (null == obj) { throw ADP.InvalidCast(); @@ -845,8 +1017,7 @@ internal static string GetString(SmiEventSink_Default sink, ITypedGettersV3 gett return (string)obj; } - - // dealing with v200 SMI + // dealing with v200 SMI internal static TimeSpan GetTimeSpan(SmiEventSink_Default sink, SmiTypedGetterSetter getters, int ordinal, SmiMetaData metaData) { ThrowIfITypedGettersIsNull(sink, getters, ordinal); @@ -854,7 +1025,11 @@ internal static TimeSpan GetTimeSpan(SmiEventSink_Default sink, SmiTypedGetterSe { return GetTimeSpan_Unchecked(sink, getters, ordinal); } - return (TimeSpan)GetValue200(sink, getters, ordinal, metaData); + return (TimeSpan)GetValue200(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , null +#endif + ); } // GetValue() for v200 SMI (new Katmai Date/Time types) @@ -863,6 +1038,9 @@ internal static object GetValue200( SmiTypedGetterSetter getters, int ordinal, SmiMetaData metaData +#if NETFRAMEWORK + ,SmiContext context +#endif ) { object result = null; @@ -878,7 +1056,11 @@ SmiMetaData metaData metaData = getters.GetVariantType(sink, ordinal); sink.ProcessMessagesAndThrow(); Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant causes endless recursion!"); - result = GetValue200(sink, getters, ordinal, metaData); + result = GetValue200(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , context +#endif + ); break; case SqlDbType.Date: case SqlDbType.DateTime2: @@ -891,7 +1073,11 @@ SmiMetaData metaData result = GetDateTimeOffset_Unchecked(sink, getters, ordinal); break; default: - result = GetValue(sink, getters, ordinal, metaData); + result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , context +#endif + ); break; } } @@ -905,6 +1091,9 @@ internal static object GetValue( ITypedGettersV3 getters, int ordinal, SmiMetaData metaData +#if NETFRAMEWORK + ,SmiContext context +#endif ) { object result = null; @@ -989,10 +1178,18 @@ SmiMetaData metaData metaData = getters.GetVariantType(sink, ordinal); sink.ProcessMessagesAndThrow(); Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant causes endless recursion!"); - result = GetValue(sink, getters, ordinal, metaData); + result = GetValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , context +#endif + ); break; case SqlDbType.Xml: - result = GetSqlXml_Unchecked(sink, getters, ordinal).Value; + result = GetSqlXml_Unchecked(sink, getters, ordinal +#if NETFRAMEWORK + , context +#endif + ).Value; break; case SqlDbType.Udt: result = GetUdt_LengthChecked(sink, getters, ordinal, metaData); @@ -1009,6 +1206,9 @@ internal static object GetSqlValue200( SmiTypedGetterSetter getters, int ordinal, SmiMetaData metaData +#if NETFRAMEWORK + ,SmiContext context +#endif ) { object result = null; @@ -1031,7 +1231,11 @@ SmiMetaData metaData metaData = getters.GetVariantType(sink, ordinal); sink.ProcessMessagesAndThrow(); Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant causes endless recursion!"); - result = GetSqlValue200(sink, getters, ordinal, metaData); + result = GetSqlValue200(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , context +#endif + ); break; case SqlDbType.Date: case SqlDbType.DateTime2: @@ -1044,7 +1248,11 @@ SmiMetaData metaData result = GetDateTimeOffset_Unchecked(sink, getters, ordinal); break; default: - result = GetSqlValue(sink, getters, ordinal, metaData); + result = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , context +#endif + ); break; } } @@ -1058,6 +1266,9 @@ internal static object GetSqlValue( ITypedGettersV3 getters, int ordinal, SmiMetaData metaData +#if NETFRAMEWORK + ,SmiContext context +#endif ) { object result = null; @@ -1149,10 +1360,18 @@ SmiMetaData metaData metaData = getters.GetVariantType(sink, ordinal); sink.ProcessMessagesAndThrow(); Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant causes endless recursion!"); - result = GetSqlValue(sink, getters, ordinal, metaData); + result = GetSqlValue(sink, getters, ordinal, metaData +#if NETFRAMEWORK + , context +#endif + ); break; case SqlDbType.Xml: - result = GetSqlXml_Unchecked(sink, getters, ordinal); + result = GetSqlXml_Unchecked(sink, getters, ordinal +#if NETFRAMEWORK + , context +#endif + ); break; case SqlDbType.Udt: result = GetUdt_LengthChecked(sink, getters, ordinal, metaData); @@ -1164,7 +1383,7 @@ SmiMetaData metaData } // null return values for SqlClient 1.1-compatible GetSqlValue() - private static object[] s_typeSpecificNullForSqlValue = { + private static readonly object[] s_typeSpecificNullForSqlValue = { SqlInt64.Null, // SqlDbType.BigInt SqlBinary.Null, // SqlDbType.Binary SqlBoolean.Null, // SqlDbType.Bit @@ -1206,7 +1425,7 @@ internal static object NullUdtInstance(SmiMetaData metaData) { Type t = metaData.Type; Debug.Assert(t != null, "Unexpected null of Udt type on NullUdtInstance!"); - return t.InvokeMember("Null", BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Static, null, null, Array.Empty(), CultureInfo.InvariantCulture); + return t.InvokeMember("Null", BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Static, null, null, new object[] { }, CultureInfo.InvariantCulture); } // Strongly-typed setters are a bit simpler than their corresponding getters. @@ -1300,8 +1519,18 @@ internal static void SetDateTime(SmiEventSink_Default sink, ITypedSettersV3 sett SetDateTime_Checked(sink, setters, ordinal, metaData, value); } - internal static void SetDateTimeOffset(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTimeOffset value) + internal static void SetDateTimeOffset(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, DateTimeOffset value +#if NETFRAMEWORK + , bool settersSupportKatmaiDateTime +#endif + ) { +#if NETFRAMEWORK + if (!settersSupportKatmaiDateTime) + { + throw ADP.InvalidCast(); + } +#endif ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.DateTimeOffset); SetDateTimeOffset_Unchecked(sink, (SmiTypedGetterSetter)setters, ordinal, value); } @@ -1471,8 +1700,18 @@ internal static void SetString(SmiEventSink_Default sink, ITypedSettersV3 setter SetString_LengthChecked(sink, setters, ordinal, metaData, value, 0); } - internal static void SetTimeSpan(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, TimeSpan value) + internal static void SetTimeSpan(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, TimeSpan value +#if NETFRAMEWORK + , bool settersSupportKatmaiDateTime +#endif + ) { +#if NETFRAMEWORK + if (!settersSupportKatmaiDateTime) + { + throw ADP.InvalidCast(); + } +#endif ThrowIfInvalidSetterAccess(metaData, ExtendedClrTypeCode.TimeSpan); SetTimeSpan_Checked(sink, (SmiTypedGetterSetter)setters, ordinal, metaData, value); } @@ -1711,57 +1950,6 @@ ParameterPeekAheadValue peekAhead } } - private static void SetDataTable_Unchecked( - SmiEventSink_Default sink, - SmiTypedGetterSetter setters, - int ordinal, - SmiMetaData metaData, - DataTable value - ) - { - // Get the target gettersetter - setters = setters.GetTypedGetterSetter(sink, ordinal); - sink.ProcessMessagesAndThrow(); - - // iterate over all records - // if first record was obtained earlier, use it prior to pulling more - ExtendedClrTypeCode[] cellTypes = new ExtendedClrTypeCode[metaData.FieldMetaData.Count]; - for (int i = 0; i < metaData.FieldMetaData.Count; i++) - { - cellTypes[i] = ExtendedClrTypeCode.Invalid; - } - foreach (DataRow row in value.Rows) - { - setters.NewElement(sink); - sink.ProcessMessagesAndThrow(); - - // Set all columns in the record - for (int i = 0; i < metaData.FieldMetaData.Count; i++) - { - SmiMetaData fieldMetaData = metaData.FieldMetaData[i]; - if (row.IsNull(i)) - { - SetDBNull_Unchecked(sink, setters, i); - } - else - { - object cellValue = row[i]; - - // Only determine cell types for first row, to save expensive - if (ExtendedClrTypeCode.Invalid == cellTypes[i]) - { - cellTypes[i] = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType( - fieldMetaData.SqlDbType, fieldMetaData.IsMultiValued, cellValue, fieldMetaData.Type); - } - SetCompatibleValueV200(sink, setters, i, fieldMetaData, cellValue, cellTypes[i], 0, NoLengthLimit, null); - } - } - } - - setters.EndElements(sink); - sink.ProcessMessagesAndThrow(); - } - // Copy multiple fields from reader to ITypedSettersV3 // Assumes caller enforces that reader and setter metadata are compatible internal static void FillCompatibleITypedSettersFromReader(SmiEventSink_Default sink, ITypedSettersV3 setters, SmiMetaData[] metaData, SqlDataReader reader) @@ -1929,8 +2117,7 @@ internal static void FillCompatibleSettersFromReader(SmiEventSink_Default sink, { // block to scope sqlReader local to avoid conflicts Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlDecimal)); // Support full fidelity for SqlDataReader - SqlDataReader sqlReader = reader as SqlDataReader; - if (null != sqlReader) + if (reader is SqlDataReader sqlReader) { SetSqlDecimal_Unchecked(sink, setters, i, sqlReader.GetSqlDecimal(i)); } @@ -2005,8 +2192,7 @@ internal static void FillCompatibleSettersFromReader(SmiEventSink_Default sink, case SqlDbType.Xml: { Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlXml)); - SqlDataReader sqlReader = reader as SqlDataReader; - if (null != sqlReader) + if (reader is SqlDataReader sqlReader) { SetSqlXml_Unchecked(sink, setters, i, sqlReader.GetSqlXml(i)); } @@ -2019,10 +2205,9 @@ internal static void FillCompatibleSettersFromReader(SmiEventSink_Default sink, case SqlDbType.Variant: { // block to scope sqlReader local and avoid conflicts // Support better options for SqlDataReader - SqlDataReader sqlReader = reader as SqlDataReader; SqlBuffer.StorageType storageType = SqlBuffer.StorageType.Empty; object o; - if (null != sqlReader) + if (reader is SqlDataReader sqlReader) { o = sqlReader.GetSqlValue(i); storageType = sqlReader.GetVariantInternalStorageType(i); @@ -2031,7 +2216,13 @@ internal static void FillCompatibleSettersFromReader(SmiEventSink_Default sink, { o = reader.GetValue(i); } - ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType(metaData[i].SqlDbType, metaData[i].IsMultiValued, o, null); + ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType(metaData[i].SqlDbType, metaData[i].IsMultiValued, o, null +#if NETFRAMEWORK + ,// TODO: this version works for shipping Orcas, since only Katmai (TVP) codepath calls this method at this time. + // Need a better story for smi versioning of ValueUtilsSmi post-Orcas + SmiContextFactory.KatmaiVersion +#endif + ); if ((storageType == SqlBuffer.StorageType.DateTime2) || (storageType == SqlBuffer.StorageType.Date)) SetCompatibleValueV200(sink, setters, i, metaData[i], o, typeCode, 0, 0, null, storageType); else @@ -2055,9 +2246,8 @@ internal static void FillCompatibleSettersFromReader(SmiEventSink_Default sink, case SqlDbType.Time: { // block to scope sqlReader local and avoid conflicts Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.TimeSpan)); - SqlDataReader sqlReader = reader as SqlDataReader; TimeSpan ts; - if (null != sqlReader) + if (reader is SqlDataReader sqlReader) { ts = sqlReader.GetTimeSpan(i); } @@ -2071,9 +2261,8 @@ internal static void FillCompatibleSettersFromReader(SmiEventSink_Default sink, case SqlDbType.DateTimeOffset: { // block to scope sqlReader local and avoid conflicts Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTimeOffset)); - SqlDataReader sqlReader = reader as SqlDataReader; DateTimeOffset dto; - if (null != sqlReader) + if (reader is SqlDataReader sqlReader) { dto = sqlReader.GetDateTimeOffset(i); } @@ -2097,7 +2286,6 @@ internal static void FillCompatibleSettersFromReader(SmiEventSink_Default sink, } } - internal static void FillCompatibleSettersFromRecord(SmiEventSink_Default sink, SmiTypedGetterSetter setters, SmiMetaData[] metaData, SqlDataRecord record, SmiDefaultFieldsProperty useDefaultValues) { for (int i = 0; i < metaData.Length; ++i) @@ -2221,9 +2409,8 @@ internal static void FillCompatibleSettersFromRecord(SmiEventSink_Default sink, case SqlDbType.Time: { // block to scope sqlReader local and avoid conflicts Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.TimeSpan)); - SqlDataRecord sqlRecord = record as SqlDataRecord; TimeSpan ts; - if (null != sqlRecord) + if (record is SqlDataRecord sqlRecord) { ts = sqlRecord.GetTimeSpan(i); } @@ -2237,9 +2424,8 @@ internal static void FillCompatibleSettersFromRecord(SmiEventSink_Default sink, case SqlDbType.DateTimeOffset: { // block to scope sqlReader local and avoid conflicts Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTimeOffset)); - SqlDataRecord sqlRecord = record as SqlDataRecord; DateTimeOffset dto; - if (null != sqlRecord) + if (record is SqlDataRecord sqlRecord) { dto = sqlRecord.GetDateTimeOffset(i); } @@ -2258,36 +2444,7 @@ internal static void FillCompatibleSettersFromRecord(SmiEventSink_Default sink, } } } - - // spool a Stream into a scratch stream from the Smi interface and return it as a Stream - internal static Stream CopyIntoNewSmiScratchStream(Stream source, SmiEventSink_Default sink) - { - Stream dest = new MemoryStream(); - - int chunkSize; - if (source.CanSeek && __maxByteChunkSize > source.Length) - { - chunkSize = unchecked((int)source.Length); // unchecked cast is safe due to check on line above - } - else - { - chunkSize = __maxByteChunkSize; - } - - byte[] copyBuffer = new byte[chunkSize]; - int bytesRead; - while (0 != (bytesRead = source.Read(copyBuffer, 0, chunkSize))) - { - dest.Write(copyBuffer, 0, bytesRead); - } - dest.Flush(); - - // Need to re-wind scratch stream to beginning before returning - dest.Seek(0, SeekOrigin.Begin); - - return dest; - } - + // // Common utility code to get lengths correct for trimming // @@ -2342,8 +2499,8 @@ private static void SetDecimal_PossiblyMoney(SmiEventSink_Default sink, ITypedSe } // Hard coding smalldatetime limits... - private static readonly DateTime s_dtSmallMax = new DateTime(2079, 06, 06, 23, 59, 29, 998); - private static readonly DateTime s_dtSmallMin = new DateTime(1899, 12, 31, 23, 59, 29, 999); + private static readonly DateTime s_dtSmallMax = new(2079, 06, 06, 23, 59, 29, 998); + private static readonly DateTime s_dtSmallMin = new(1899, 12, 31, 23, 59, 29, 999); private static void VerifyDateTimeRange(SqlDbType dbType, DateTime value) { if (SqlDbType.SmallDateTime == dbType && (s_dtSmallMax < value || s_dtSmallMin > value)) @@ -2353,7 +2510,7 @@ private static void VerifyDateTimeRange(SqlDbType dbType, DateTime value) } private static readonly TimeSpan s_timeMin = TimeSpan.Zero; - private static readonly TimeSpan s_timeMax = new TimeSpan(TimeSpan.TicksPerDay - 1); + private static readonly TimeSpan s_timeMax = new(TimeSpan.TicksPerDay - 1); private static void VerifyTimeRange(SqlDbType dbType, TimeSpan value) { if (SqlDbType.Time == dbType && (s_timeMin > value || value > s_timeMax)) @@ -2435,7 +2592,6 @@ private static void SetSqlBinary_LengthChecked(SmiEventSink_Default sink, ITyped private static void SetBytes_FromRecord(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlDataRecord record, int offset) { - int length = 0; // Deal with large values by sending bufferLength of NoLengthLimit (== assume // CheckXetParameters will ignore requested-length checks in this case @@ -2444,7 +2600,7 @@ private static void SetBytes_FromRecord(SmiEventSink_Default sink, ITypedSetters { bufferLength = NoLengthLimit; } - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, checked((int)bufferLength), offset, checked((int)bufferLength)); + int length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, checked((int)bufferLength), offset, checked((int)bufferLength)); int chunkSize; if (length > __maxByteChunkSize || length < 0) @@ -2485,11 +2641,10 @@ private static void SetBytes_FromRecord(SmiEventSink_Default sink, ITypedSetters private static void SetBytes_FromReader(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, SmiMetaData metaData, DbDataReader reader, int offset) { - int length = 0; // Deal with large values by sending bufferLength of NoLengthLimit (== assume // CheckXetParameters will ignore requested-length checks in this case) - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, NoLengthLimit /* buffer length */, offset, NoLengthLimit /* requested length */ ); + int length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, NoLengthLimit /* buffer length */, offset, NoLengthLimit /* requested length */ ); // Use fixed chunk size for all cases to avoid inquiring from reader. int chunkSize = __maxByteChunkSize; @@ -2540,7 +2695,6 @@ private static void SetSqlBytes_LengthChecked(SmiEventSink_Default sink, ITypedS private static void SetChars_FromRecord(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, SmiMetaData metaData, SqlDataRecord record, int offset) { - int length = 0; // Deal with large values by sending bufferLength of NoLengthLimit // CheckXetParameters will ignore length checks in this case @@ -2549,7 +2703,7 @@ private static void SetChars_FromRecord(SmiEventSink_Default sink, ITypedSetters { bufferLength = NoLengthLimit; } - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, checked((int)bufferLength), offset, checked((int)bufferLength - offset)); + int length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, checked((int)bufferLength), offset, checked((int)bufferLength - offset)); int chunkSize; if (length > __maxCharChunkSize || length < 0) @@ -2623,11 +2777,10 @@ private static void SetCharsOrString_FromReader(SmiEventSink_Default sink, SmiTy // Use chunking via SetChars to transfer a value from a reader to a gettersetter private static void SetChars_FromReader(SmiEventSink_Default sink, SmiTypedGetterSetter setters, int ordinal, SmiMetaData metaData, DbDataReader reader, int offset) { - int length = 0; // Deal with large values by sending bufferLength of NoLengthLimit (== assume // CheckXetParameters will ignore requested-length checks in this case) - length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, NoLengthLimit /* buffer length */, offset, NoLengthLimit /* requested length */ ); + int length = CheckXetParameters(metaData.SqlDbType, metaData.MaxLength, NoLengthLimit /* actual */, 0, NoLengthLimit /* buffer length */, offset, NoLengthLimit /* requested length */ ); // Use fixed chunk size for all cases to avoid inquiring from reader. int chunkSize; @@ -2903,199 +3056,109 @@ private static int CheckXetParameters( private const bool X = true; private const bool _ = false; - private static bool[,] s_canAccessGetterDirectly = { + private static readonly bool[,] s_canAccessGetterDirectly = { // SqlDbTypes as columns (abbreviated, but in order) // ExtendedClrTypeCodes as rows - // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO - /*Bool*/ - { _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Bool*/ - /*Byte*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Byte*/ - /*Char*/ - { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Char*/ - /*DTime*/ - { _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*DateTime*/ - /*DBNul*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*DBNull*/ - /*Decim*/ - { _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Decimal*/ - /*Doubl*/ - { _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Double*/ - /*Empty*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Empty*/ - /*Int16*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int16*/ - /*Int32*/ - { _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int32*/ - /*Int64*/ - { X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int64*/ - /*SByte*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SByte*/ - /*Singl*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Single*/ - /*Strng*/ - { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*String*/ - /*UIn16*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt16*/ - /*UIn32*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt32*/ - /*UIn64*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt64*/ - /*Objct*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*Object*/ - /*BytAr*/ - { _ , X , _ , X , _ , _ , _ , X , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , X , _ , X , X , _ , _ , X , _ , _ , _ , X , _, _ , _ , _ , _ , },/*ByteArray*/ - /*ChrAr*/ - { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*CharArray*/ - /*Guid*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Guid*/ - /*SBin*/ - { _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBinary*/ - /*SBool*/ - { _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlBoolean*/ - /*SByte*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlByte*/ - /*SDTme*/ - { _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*SqlDateTime*/ - /*SDubl*/ - { _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDouble*/ - /*SGuid*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlGuid*/ - /*SIn16*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt16*/ - /*SIn32*/ - { _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt32*/ - /*SIn64*/ - { X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt64*/ - /*SMony*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlMoney*/ - /*SDeci*/ - { _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDecimal*/ - /*SSngl*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlSingle*/ - /*SStrn*/ - { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlString*/ - /*SChrs*/ - { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlChars*/ - /*SByts*/ - { _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBytes*/ - /*SXml*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlXml*/ - /*DTbl*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DataTable*/ - /*Rdr */ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DbDataReader*/ - /*EnSDR*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*IEnurerable*/ - /*TmSpn*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , X , _ , _ , },/*TimeSpan*/ - /*DTOst*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , X , },/*DateTimeOffset*/ - /*Strm */ - { _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*Stream*/ - /*TxRdr*/ - { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*TextReader*/ - /*XmlRd*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*XmlReader*/ - // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO + // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO +/*Bool*/ { _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Bool*/ +/*Byte*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Byte*/ +/*Char*/ { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Char*/ +/*DTime*/{ _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*DateTime*/ +/*DBNul*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*DBNull*/ +/*Decim*/{ _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Decimal*/ +/*Doubl*/{ _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Double*/ +/*Empty*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Empty*/ +/*Int16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int16*/ +/*Int32*/{ _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int32*/ +/*Int64*/{ X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int64*/ +/*SByte*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SByte*/ +/*Singl*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Single*/ +/*Strng*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*String*/ +/*UIn16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt16*/ +/*UIn32*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt32*/ +/*UIn64*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt64*/ +/*Objct*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*Object*/ +/*BytAr*/{ _ , X , _ , X , _ , _ , _ , X , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , X , _ , X , X , _ , _ , X , _ , _ , _ , X , _, _ , _ , _ , _ , },/*ByteArray*/ +/*ChrAr*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*CharArray*/ +/*Guid*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Guid*/ +/*SBin*/ { _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBinary*/ +/*SBool*/{ _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlBoolean*/ +/*SByte*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlByte*/ +/*SDTme*/{ _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*SqlDateTime*/ +/*SDubl*/{ _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDouble*/ +/*SGuid*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlGuid*/ +/*SIn16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt16*/ +/*SIn32*/{ _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt32*/ +/*SIn64*/{ X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt64*/ +/*SMony*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlMoney*/ +/*SDeci*/{ _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDecimal*/ +/*SSngl*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlSingle*/ +/*SStrn*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlString*/ +/*SChrs*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlChars*/ +/*SByts*/{ _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBytes*/ +/*SXml*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlXml*/ +/*DTbl*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DataTable*/ +/*Rdr */ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DbDataReader*/ +/*EnSDR*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*IEnurerable*/ +/*TmSpn*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , X , _ , _ , },/*TimeSpan*/ +/*DTOst*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , X , },/*DateTimeOffset*/ +/*Strm */{ _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*Stream*/ +/*TxRdr*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*TextReader*/ +/*XmlRd*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*XmlReader*/ + // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO }; - private static bool[,] s_canAccessSetterDirectly = { - // Setters as columns (labels are abbreviated from ExtendedClrTypeCode names) - // SqlDbTypes as rows - // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO - /*Bool*/ - { _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Bool*/ - /*Byte*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Byte*/ - /*Char*/ - { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Char*/ - /*DTime*/ - { _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*DateTime*/ - /*DBNul*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*DBNull*/ - /*Decim*/ - { _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Decimal*/ - /*Doubl*/ - { _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Double*/ - /*Empty*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Empty*/ - /*Int16*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int16*/ - /*Int32*/ - { _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int32*/ - /*Int64*/ - { X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int64*/ - /*SByte*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SByte*/ - /*Singl*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Single*/ - /*Strng*/ - { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*String*/ - /*UIn16*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt16*/ - /*UIn32*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt32*/ - /*UIn64*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt64*/ - /*Objct*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*Object*/ - /*BytAr*/ - { _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , X , _ , X , _ , _ , _ , X , _, _ , _ , _ , _ , },/*ByteArray*/ - /*ChrAr*/ - { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*CharArray*/ - /*Guid*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Guid*/ - /*SBin*/ - { _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , X , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBinary*/ - /*SBool*/ - { _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlBoolean*/ - /*SByte*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlByte*/ - /*SDTme*/ - { _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*SqlDateTime*/ - /*SDubl*/ - { _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDouble*/ - /*SGuid*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlGuid*/ - /*SIn16*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt16*/ - /*SIn32*/ - { _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt32*/ - /*SIn64*/ - { X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt64*/ - /*SMony*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlMoney*/ - /*SDeci*/ - { _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDecimal*/ - /*SSngl*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlSingle*/ - /*SStrn*/ - { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlString*/ - /*SChrs*/ - { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlChars*/ - /*SByts*/ - { _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , X , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBytes*/ - /*SXml*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlXml*/ - /*DTbl*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DataTable*/ - /*Rdr */ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DbDataReader*/ - /*EnSDR*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*IEnurerable*/ - /*TmSpn*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , X , _ , _ , },/*TimeSpan*/ - /*DTOst*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , X , },/*DateTimeOffset*/ - /*Strm */ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Stream*/ - /*TxRdr*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*TextReader*/ - /*XmlRd*/ - { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*XmlReader*/ - // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO + private static readonly bool[,] s_canAccessSetterDirectly = { + // Setters as columns (labels are abreviated from ExtendedClrTypeCode names) + // SqlDbTypes as rows + // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO +/*Bool*/ { _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Bool*/ +/*Byte*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Byte*/ +/*Char*/ { _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Char*/ +/*DTime*/{ _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*DateTime*/ +/*DBNul*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*DBNull*/ +/*Decim*/{ _ , _ , _ , _ , _ , X , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Decimal*/ +/*Doubl*/{ _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Double*/ +/*Empty*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Empty*/ +/*Int16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int16*/ +/*Int32*/{ _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int32*/ +/*Int64*/{ X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Int64*/ +/*SByte*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SByte*/ +/*Singl*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Single*/ +/*Strng*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*String*/ +/*UIn16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt16*/ +/*UIn32*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt32*/ +/*UIn64*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*UInt64*/ +/*Objct*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*Object*/ +/*BytAr*/{ _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , X , _ , X , _ , _ , _ , X , _, _ , _ , _ , _ , },/*ByteArray*/ +/*ChrAr*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*CharArray*/ +/*Guid*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Guid*/ +/*SBin*/ { _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , X , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBinary*/ +/*SBool*/{ _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlBoolean*/ +/*SByte*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlByte*/ +/*SDTme*/{ _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, X , _ , X , _ , },/*SqlDateTime*/ +/*SDubl*/{ _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDouble*/ +/*SGuid*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlGuid*/ +/*SIn16*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt16*/ +/*SIn32*/{ _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt32*/ +/*SIn64*/{ X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlInt64*/ +/*SMony*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlMoney*/ +/*SDeci*/{ _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlDecimal*/ +/*SSngl*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlSingle*/ +/*SStrn*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlString*/ +/*SChrs*/{ _ , _ , _ , X , _ , _ , _ , _ , _ , _ , X , X , X , _ , _ , _ , _ , _ , X , _ , _ , _ , X , X , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlChars*/ +/*SByts*/{ _ , X , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , X , _ , X , _ , _ , _ , _ , _ , X , _, _ , _ , _ , _ , },/*SqlBytes*/ +/*SXml*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*SqlXml*/ +/*DTbl*/ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DataTable*/ +/*Rdr */ { _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*DbDataReader*/ +/*EnSDR*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , X, _ , _ , _ , _ , },/*IEnurerable*/ +/*TmSpn*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , X , _ , _ , },/*TimeSpan*/ +/*DTOst*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , X , },/*DateTimeOffset*/ +/*Strm */{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*Stream*/ +/*TxRdr*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*TextReader*/ +/*XmlRd*/{ _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _ , _, _ , _ , _ , _ , },/*XmlReader*/ + // BI, Bin, Bit, Ch, DT, Dec, Fl, Im, Int, Mny, NCh, NTx, NVC, Rl, UI, SDT, SI, SMn, Txt, TS, TI, VBn, VCh, Var, 24, Xml, 26, 27, 28, Udt, St, Dat, Tm, DT2, DTO }; @@ -3303,16 +3366,32 @@ private static SqlMoney GetSqlMoney_Unchecked(SmiEventSink_Default sink, ITypedG return SqlTypeWorkarounds.SqlMoneyCtor(temp, 1 /* ignored */ ); } - private static SqlXml GetSqlXml_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal) + private static SqlXml GetSqlXml_Unchecked(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal +#if NETFRAMEWORK + , SmiContext context +#endif + ) { Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - - +#if NETFRAMEWORK + // allow context to be null so strongly-typed getters can use + // this method without having to pass along the almost-never-used context as a parameter + // Looking the context up like this will be slightly slower, but still correct behavior + // since it's only used to get a scratch stream. + if (null == context && InOutOfProcHelper.InProc) + { + context = SmiContextFactory.Instance.GetCurrentContext(); // In the future we need to push the context checking to a higher level + } +#endif // Note: must make a copy of getter stream, since it will be used beyond // this method (valid lifetime of getters is limited). Stream s = new SmiGettersStream(sink, getters, ordinal, SmiMetaData.DefaultXml); - Stream copy = ValueUtilsSmi.CopyIntoNewSmiScratchStream(s, sink); - SqlXml result = new SqlXml(copy); + Stream copy = ValueUtilsSmi.CopyIntoNewSmiScratchStream(s, sink +#if NETFRAMEWORK + , context +#endif + ); + SqlXml result = new(copy); return result; } @@ -3320,7 +3399,7 @@ private static string GetString_Unchecked(SmiEventSink_Default sink, ITypedGette { Debug.Assert(!IsDBNull_Unchecked(sink, getters, ordinal)); - // Note: depending on different getters, the result string maybe truncated, e.g. for + // Note: depending on different getters, the result string may be truncated, e.g. for // Inproc process, the getter is InProcRecordBuffer (implemented in SqlAcess), string will be // truncated to 4000 (if length is more than 4000). If MemoryRecordBuffer getter is used, data // is not truncated. Please refer VSDD 479655 for more detailed information regarding the string length. @@ -3362,7 +3441,6 @@ private static void SetStream_Unchecked(SmiEventSink_Default sink, ITypedSetters int nWritten = 0; do { - int nRead = 0; int readSize = constBinBufferSize; if (len > 0 && nWritten + readSize > len) { @@ -3371,7 +3449,7 @@ private static void SetStream_Unchecked(SmiEventSink_Default sink, ITypedSetters Debug.Assert(readSize >= 0); - nRead = feed._source.Read(buff, 0, readSize); + int nRead = feed._source.Read(buff, 0, readSize); if (nRead == 0) { @@ -3395,7 +3473,6 @@ private static void SetTextReader_Unchecked(SmiEventSink_Default sink, ITypedSet int nWritten = 0; do { - int nRead = 0; int readSize = constTextBufferSize; if (len > 0 && nWritten + readSize > len) { @@ -3404,7 +3481,7 @@ private static void SetTextReader_Unchecked(SmiEventSink_Default sink, ITypedSet Debug.Assert(readSize >= 0); - nRead = feed._source.Read(buff, 0, readSize); + int nRead = feed._source.Read(buff, 0, readSize); if (nRead == 0) { @@ -3834,7 +3911,7 @@ private static void SetSqlXml_Unchecked(SmiEventSink_Default sink, ITypedSetters private static void SetXmlReader_Unchecked(SmiEventSink_Default sink, ITypedSettersV3 setters, int ordinal, XmlReader xmlReader) { // set up writer - XmlWriterSettings WriterSettings = new XmlWriterSettings(); + XmlWriterSettings WriterSettings = new(); WriterSettings.CloseOutput = false; // don't close the memory stream WriterSettings.ConformanceLevel = ConformanceLevel.Fragment; WriterSettings.Encoding = System.Text.Encoding.Unicode; @@ -3860,8 +3937,7 @@ private static void SetString_Unchecked(SmiEventSink_Default sink, ITypedSetters sink.ProcessMessagesAndThrow(); } - - // Set a DbDataReader to a Structured+MultiValued setter (table type) + // Set a DbDataReader to a Structured+MultiValued setter (table type) // Assumes metaData correctly describes the reader's shape, and consumes only the current resultset private static void SetDbDataReader_Unchecked( SmiEventSink_Default sink, @@ -3962,13 +4038,115 @@ ParameterPeekAheadValue peekAhead finally { // Clean up! - IDisposable disposable = enumerator as IDisposable; - if (null != disposable) + if (enumerator is IDisposable disposable) { disposable.Dispose(); } } } + + private static void SetDataTable_Unchecked( + SmiEventSink_Default sink, + SmiTypedGetterSetter setters, + int ordinal, + SmiMetaData metaData, + DataTable value + ) + { + // Get the target gettersetter + setters = setters.GetTypedGetterSetter(sink, ordinal); + sink.ProcessMessagesAndThrow(); + + // iterate over all records + // if first record was obtained earlier, use it prior to pulling more + ExtendedClrTypeCode[] cellTypes = new ExtendedClrTypeCode[metaData.FieldMetaData.Count]; + for (int i = 0; i < metaData.FieldMetaData.Count; i++) + { + cellTypes[i] = ExtendedClrTypeCode.Invalid; + } + foreach (DataRow row in value.Rows) + { + setters.NewElement(sink); + sink.ProcessMessagesAndThrow(); + + // Set all columns in the record + for (int i = 0; i < metaData.FieldMetaData.Count; i++) + { + SmiMetaData fieldMetaData = metaData.FieldMetaData[i]; + if (row.IsNull(i)) + { + SetDBNull_Unchecked(sink, setters, i); + } + else + { + object cellValue = row[i]; + + // Only determine cell types for first row, to save expensive + if (ExtendedClrTypeCode.Invalid == cellTypes[i]) + { + cellTypes[i] = MetaDataUtilsSmi.DetermineExtendedTypeCodeForUseWithSqlDbType( + fieldMetaData.SqlDbType, fieldMetaData.IsMultiValued, cellValue, fieldMetaData.Type +#if NETFRAMEWORK + ,// TODO: this version works for shipping Orcas, since only Katmai supports TVPs at this time. + // Need a better story for smi versioning of ValueUtilsSmi post-Orcas + SmiContextFactory.KatmaiVersion +#endif + ); + } + SetCompatibleValueV200(sink, setters, i, fieldMetaData, cellValue, cellTypes[i], 0, NoLengthLimit, null); + } + } + } + + setters.EndElements(sink); + sink.ProcessMessagesAndThrow(); + } + + // spool a Stream into a scratch stream from the Smi interface and return it as a Stream + internal static Stream CopyIntoNewSmiScratchStream(Stream source, SmiEventSink_Default sink +#if NETFRAMEWORK + , SmiContext context +#endif + ) + { +#if NETFRAMEWORK + Stream dest; + if (null == context) + { + dest = new MemoryStream(); + } + else + { + dest = new SqlClientWrapperSmiStream(sink, context.GetScratchStream(sink)); + } +#else + Stream dest = new MemoryStream(); +#endif + + int chunkSize; + if (source.CanSeek && __maxByteChunkSize > source.Length) + { + chunkSize = unchecked((int)source.Length); // unchecked cast is safe due to check on line above + } + else + { + chunkSize = __maxByteChunkSize; + } + + byte[] copyBuffer = new byte[chunkSize]; + int bytesRead; + while (0 != (bytesRead = source.Read(copyBuffer, 0, chunkSize))) + { + dest.Write(copyBuffer, 0, bytesRead); + } + dest.Flush(); + + // Need to re-wind scratch stream to beginning before returning + dest.Seek(0, SeekOrigin.Begin); + + return dest; + } + } } diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.netfx.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.netfx.cs new file mode 100644 index 0000000000..d48a8df2e1 --- /dev/null +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/Server/ValueUtilsSmi.netfx.cs @@ -0,0 +1,513 @@ +using System; +using System.Collections.Generic; +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.Xml; +using Microsoft.Data.Common; +using Microsoft.Data.SqlTypes; + +namespace Microsoft.Data.SqlClient.Server +{ + // Utilities for manipulating values with the Smi interface. + // + // THIS CLASS IS BUILT ON TOP OF THE SMI INTERFACE -- SMI SHOULD NOT DEPEND ON IT! + // + // These are all based off of knowing the clr type of the value + // as an ExtendedClrTypeCode enum for rapid access (lookup in static array is best, if possible). + internal static partial class ValueUtilsSmi + { + + internal static SqlSequentialStreamSmi GetSequentialStream(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, bool bypassTypeCheck = false) + { + Debug.Assert(!ValueUtilsSmi.IsDBNull_Unchecked(sink, getters, ordinal), "Should not try to get a SqlSequentialStreamSmi on a null column"); + ThrowIfITypedGettersIsNull(sink, getters, ordinal); + if ((!bypassTypeCheck) && (!CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Stream))) + { + throw ADP.InvalidCast(); + } + + // This will advance the column to ordinal + long length = GetBytesLength_Unchecked(sink, getters, ordinal); + return new SqlSequentialStreamSmi(sink, getters, ordinal, length); + } + + internal static SqlSequentialTextReaderSmi GetSequentialTextReader(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) + { + Debug.Assert(!ValueUtilsSmi.IsDBNull_Unchecked(sink, getters, ordinal), "Should not try to get a SqlSequentialTextReaderSmi on a null column"); + ThrowIfITypedGettersIsNull(sink, getters, ordinal); + if (!CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.TextReader)) + { + throw ADP.InvalidCast(); + } + + // This will advance the column to ordinal + long length = GetCharsLength_Unchecked(sink, getters, ordinal); + return new SqlSequentialTextReaderSmi(sink, getters, ordinal, length); + } + + internal static Stream GetStream(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, bool bypassTypeCheck = false) + { + bool isDbNull = ValueUtilsSmi.IsDBNull_Unchecked(sink, getters, ordinal); + + // If a sql_variant, get the internal type + if (!bypassTypeCheck) + { + if ((!isDbNull) && (metaData.SqlDbType == SqlDbType.Variant)) + { + metaData = getters.GetVariantType(sink, ordinal); + } + // If the SqlDbType is still variant, then it must contain null, so don't throw InvalidCast + if ((metaData.SqlDbType != SqlDbType.Variant) && (!CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.Stream))) + { + throw ADP.InvalidCast(); + } + } + + byte[] data; + if (isDbNull) + { + // "null" stream + data = new byte[0]; + } + else + { + // Read all data + data = GetByteArray_Unchecked(sink, getters, ordinal); + } + + // Wrap data in pre-built object + return new MemoryStream(data, writable: false); + } + + internal static TextReader GetTextReader(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData) + { + bool isDbNull = ValueUtilsSmi.IsDBNull_Unchecked(sink, getters, ordinal); + + // If a sql_variant, get the internal type + if ((!isDbNull) && (metaData.SqlDbType == SqlDbType.Variant)) + { + metaData = getters.GetVariantType(sink, ordinal); + } + // If the SqlDbType is still variant, then it must contain null, so don't throw InvalidCast + if ((metaData.SqlDbType != SqlDbType.Variant) && (!CanAccessGetterDirectly(metaData, ExtendedClrTypeCode.TextReader))) + { + throw ADP.InvalidCast(); + } + + string data; + if (isDbNull) + { + // "null" textreader + data = string.Empty; + } + else + { + // Read all data + data = GetString_Unchecked(sink, getters, ordinal); + } + + // Wrap in pre-built object + return new StringReader(data); + } + + // calling GetTimeSpan on possibly v100 SMI + internal static TimeSpan GetTimeSpan(SmiEventSink_Default sink, ITypedGettersV3 getters, int ordinal, SmiMetaData metaData, bool gettersSupportKatmaiDateTime) + { + if (gettersSupportKatmaiDateTime) + { + return GetTimeSpan(sink, (SmiTypedGetterSetter)getters, ordinal, metaData); + } + ThrowIfITypedGettersIsNull(sink, getters, ordinal); + object obj = GetValue(sink, getters, ordinal, metaData, null); + if (null == obj) + { + throw ADP.InvalidCast(); + } + return (TimeSpan)obj; + } + + internal static SqlBuffer.StorageType SqlDbTypeToStorageType(SqlDbType dbType) + { + int index = unchecked((int)dbType); + Debug.Assert(index >= 0 && index < s_dbTypeToStorageType.Length, string.Format(CultureInfo.InvariantCulture, "Unexpected dbType value: {0}", dbType)); + return s_dbTypeToStorageType[index]; + } + + private static void GetNullOutputParameterSmi(SmiMetaData metaData, SqlBuffer targetBuffer, ref object result) + { + if (SqlDbType.Udt == metaData.SqlDbType) + { + result = NullUdtInstance(metaData); + } + else + { + SqlBuffer.StorageType stype = SqlDbTypeToStorageType(metaData.SqlDbType); + if (SqlBuffer.StorageType.Empty == stype) + { + result = DBNull.Value; + } + else if (SqlBuffer.StorageType.SqlBinary == stype) + { + // special case SqlBinary, 'cause tds parser never sets SqlBuffer to null, just to empty! + targetBuffer.SqlBinary = SqlBinary.Null; + } + else if (SqlBuffer.StorageType.SqlGuid == stype) + { + targetBuffer.SqlGuid = SqlGuid.Null; + } + else + { + targetBuffer.SetToNullOfType(stype); + } + } + } + + // UDTs and null variants come back via return value, all else is via targetBuffer. + // implements SqlClient 2.0-compatible output parameter semantics + internal static object GetOutputParameterV3Smi( + SmiEventSink_Default sink, // event sink for errors + ITypedGettersV3 getters, // getters interface to grab value from + int ordinal, // parameter within getters + SmiMetaData metaData, // Getter's type for this ordinal + SmiContext context, // used to obtain scratch streams + SqlBuffer targetBuffer // destination + ) + { + object result = null; // Workaround for UDT hack in non-Smi code paths. + if (IsDBNull_Unchecked(sink, getters, ordinal)) + { + GetNullOutputParameterSmi(metaData, targetBuffer, ref result); + } + else + { + switch (metaData.SqlDbType) + { + case SqlDbType.BigInt: + targetBuffer.Int64 = GetInt64_Unchecked(sink, getters, ordinal); + break; + case SqlDbType.Binary: + case SqlDbType.Image: + case SqlDbType.Timestamp: + case SqlDbType.VarBinary: + targetBuffer.SqlBinary = GetSqlBinary_Unchecked(sink, getters, ordinal); + break; + case SqlDbType.Bit: + targetBuffer.Boolean = GetBoolean_Unchecked(sink, getters, ordinal); + break; + case SqlDbType.NChar: + case SqlDbType.NText: + case SqlDbType.NVarChar: + case SqlDbType.Char: + case SqlDbType.VarChar: + case SqlDbType.Text: + targetBuffer.SetToString(GetString_Unchecked(sink, getters, ordinal)); + break; + case SqlDbType.DateTime: + case SqlDbType.SmallDateTime: + { + SqlDateTime dt = new(GetDateTime_Unchecked(sink, getters, ordinal)); + targetBuffer.SetToDateTime(dt.DayTicks, dt.TimeTicks); + break; + } + case SqlDbType.Decimal: + { + SqlDecimal dec = GetSqlDecimal_Unchecked(sink, getters, ordinal); + targetBuffer.SetToDecimal(dec.Precision, dec.Scale, dec.IsPositive, dec.Data); + break; + } + case SqlDbType.Float: + targetBuffer.Double = GetDouble_Unchecked(sink, getters, ordinal); + break; + case SqlDbType.Int: + targetBuffer.Int32 = GetInt32_Unchecked(sink, getters, ordinal); + break; + case SqlDbType.Money: + case SqlDbType.SmallMoney: + targetBuffer.SetToMoney(GetInt64_Unchecked(sink, getters, ordinal)); + break; + case SqlDbType.Real: + targetBuffer.Single = GetSingle_Unchecked(sink, getters, ordinal); + break; + case SqlDbType.UniqueIdentifier: + targetBuffer.SqlGuid = new SqlGuid(GetGuid_Unchecked(sink, getters, ordinal)); + break; + case SqlDbType.SmallInt: + targetBuffer.Int16 = GetInt16_Unchecked(sink, getters, ordinal); + break; + case SqlDbType.TinyInt: + targetBuffer.Byte = GetByte_Unchecked(sink, getters, ordinal); + break; + case SqlDbType.Variant: + // For variants, recur using the current value's sqldbtype + metaData = getters.GetVariantType(sink, ordinal); + sink.ProcessMessagesAndThrow(); + Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant not supposed to be possible!"); + GetOutputParameterV3Smi(sink, getters, ordinal, metaData, context, targetBuffer); + break; + case SqlDbType.Udt: + result = GetUdt_LengthChecked(sink, getters, ordinal, metaData); + break; + case SqlDbType.Xml: + targetBuffer.SqlXml = GetSqlXml_Unchecked(sink, getters, ordinal, null); + break; + default: + Debug.Assert(false, "Unexpected SqlDbType"); + break; + } + } + + return result; + } + + // UDTs and null variants come back via return value, all else is via targetBuffer. + // implements SqlClient 1.1-compatible output parameter semantics + internal static object GetOutputParameterV200Smi( + SmiEventSink_Default sink, // event sink for errors + SmiTypedGetterSetter getters, // getters interface to grab value from + int ordinal, // parameter within getters + SmiMetaData metaData, // Getter's type for this ordinal + SmiContext context, // used to obtain scratch streams + SqlBuffer targetBuffer // destination + ) + { + object result = null; // Workaround for UDT hack in non-Smi code paths. + if (IsDBNull_Unchecked(sink, getters, ordinal)) + { + GetNullOutputParameterSmi(metaData, targetBuffer, ref result); + } + else + { + switch (metaData.SqlDbType) + { + // new types go here + case SqlDbType.Variant: // Handle variants specifically for v200, since they could contain v200 types + // For variants, recur using the current value's sqldbtype + metaData = getters.GetVariantType(sink, ordinal); + sink.ProcessMessagesAndThrow(); + Debug.Assert(SqlDbType.Variant != metaData.SqlDbType, "Variant-within-variant not supposed to be possible!"); + GetOutputParameterV200Smi(sink, getters, ordinal, metaData, context, targetBuffer); + break; + case SqlDbType.Date: + targetBuffer.SetToDate(GetDateTime_Unchecked(sink, getters, ordinal)); + break; + case SqlDbType.DateTime2: + targetBuffer.SetToDateTime2(GetDateTime_Unchecked(sink, getters, ordinal), metaData.Scale); + break; + case SqlDbType.Time: + targetBuffer.SetToTime(GetTimeSpan_Unchecked(sink, getters, ordinal), metaData.Scale); + break; + case SqlDbType.DateTimeOffset: + targetBuffer.SetToDateTimeOffset(GetDateTimeOffset_Unchecked(sink, getters, ordinal), metaData.Scale); + break; + default: + result = GetOutputParameterV3Smi(sink, getters, ordinal, metaData, context, targetBuffer); + break; + } + } + + return result; + } + + private static readonly SqlBuffer.StorageType[] s_dbTypeToStorageType = new SqlBuffer.StorageType[] { + SqlBuffer.StorageType.Int64, // BigInt + SqlBuffer.StorageType.SqlBinary, // Binary + SqlBuffer.StorageType.Boolean, // Bit + SqlBuffer.StorageType.String, // Char + SqlBuffer.StorageType.DateTime, // DateTime + SqlBuffer.StorageType.Decimal, // Decimal + SqlBuffer.StorageType.Double, // Float + SqlBuffer.StorageType.SqlBinary, // Image + SqlBuffer.StorageType.Int32, // Int + SqlBuffer.StorageType.Money, // Money + SqlBuffer.StorageType.String, // NChar + SqlBuffer.StorageType.String, // NText + SqlBuffer.StorageType.String, // NVarChar + SqlBuffer.StorageType.Single, // Real + SqlBuffer.StorageType.SqlGuid, // UniqueIdentifier + SqlBuffer.StorageType.DateTime, // SmallDateTime + SqlBuffer.StorageType.Int16, // SmallInt + SqlBuffer.StorageType.Money, // SmallMoney + SqlBuffer.StorageType.String, // Text + SqlBuffer.StorageType.SqlBinary, // Timestamp + SqlBuffer.StorageType.Byte, // TinyInt + SqlBuffer.StorageType.SqlBinary, // VarBinary + SqlBuffer.StorageType.String, // VarChar + SqlBuffer.StorageType.Empty, // Variant + SqlBuffer.StorageType.Empty, // 24 + SqlBuffer.StorageType.SqlXml, // Xml + SqlBuffer.StorageType.Empty, // 26 + SqlBuffer.StorageType.Empty, // 27 + SqlBuffer.StorageType.Empty, // 28 + SqlBuffer.StorageType.Empty, // Udt + SqlBuffer.StorageType.Empty, // Structured + SqlBuffer.StorageType.Date, // Date + SqlBuffer.StorageType.Time, // Time + SqlBuffer.StorageType.DateTime2, // DateTime2 + SqlBuffer.StorageType.DateTimeOffset, // DateTimeOffset + }; + + internal static void FillCompatibleITypedSettersFromRecord(SmiEventSink_Default sink, ITypedSettersV3 setters, SmiMetaData[] metaData, SqlDataRecord record) + { + FillCompatibleITypedSettersFromRecord(sink, setters, metaData, record, null); + } + + internal static void FillCompatibleITypedSettersFromRecord(SmiEventSink_Default sink, ITypedSettersV3 setters, SmiMetaData[] metaData, SqlDataRecord record, SmiDefaultFieldsProperty useDefaultValues) + { + for (int i = 0; i < metaData.Length; ++i) + { + if (null != useDefaultValues && useDefaultValues[i]) + { + continue; + } + if (record.IsDBNull(i)) + { + ValueUtilsSmi.SetDBNull_Unchecked(sink, setters, i); + } + else + { + switch (metaData[i].SqlDbType) + { + case SqlDbType.BigInt: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int64)); + SetInt64_Unchecked(sink, setters, i, record.GetInt64(i)); + break; + case SqlDbType.Binary: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); + SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); + break; + case SqlDbType.Bit: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Boolean)); + SetBoolean_Unchecked(sink, setters, i, record.GetBoolean(i)); + break; + case SqlDbType.Char: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); + SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); + break; + case SqlDbType.DateTime: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); + SetDateTime_Checked(sink, setters, i, metaData[i], record.GetDateTime(i)); + break; + case SqlDbType.Decimal: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlDecimal)); + SetSqlDecimal_Unchecked(sink, setters, i, record.GetSqlDecimal(i)); + break; + case SqlDbType.Float: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Double)); + SetDouble_Unchecked(sink, setters, i, record.GetDouble(i)); + break; + case SqlDbType.Image: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); + SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); + break; + case SqlDbType.Int: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int32)); + SetInt32_Unchecked(sink, setters, i, record.GetInt32(i)); + break; + case SqlDbType.Money: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney)); + SetSqlMoney_Unchecked(sink, setters, i, metaData[i], record.GetSqlMoney(i)); + break; + case SqlDbType.NChar: + case SqlDbType.NText: + case SqlDbType.NVarChar: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); + SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); + break; + case SqlDbType.Real: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Single)); + SetSingle_Unchecked(sink, setters, i, record.GetFloat(i)); + break; + case SqlDbType.UniqueIdentifier: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Guid)); + SetGuid_Unchecked(sink, setters, i, record.GetGuid(i)); + break; + case SqlDbType.SmallDateTime: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.DateTime)); + SetDateTime_Checked(sink, setters, i, metaData[i], record.GetDateTime(i)); + break; + case SqlDbType.SmallInt: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Int16)); + SetInt16_Unchecked(sink, setters, i, record.GetInt16(i)); + break; + case SqlDbType.SmallMoney: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlMoney)); + SetSqlMoney_Checked(sink, setters, i, metaData[i], record.GetSqlMoney(i)); + break; + case SqlDbType.Text: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlChars)); + SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); + break; + case SqlDbType.Timestamp: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); + SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); + break; + case SqlDbType.TinyInt: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.Byte)); + SetByte_Unchecked(sink, setters, i, record.GetByte(i)); + break; + case SqlDbType.VarBinary: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); + SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); + break; + case SqlDbType.VarChar: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.String)); + SetChars_FromRecord(sink, setters, i, metaData[i], record, 0); + break; + case SqlDbType.Xml: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlXml)); + SetSqlXml_Unchecked(sink, setters, i, record.GetSqlXml(i)); // perf improvement? + break; + case SqlDbType.Variant: + object o = record.GetSqlValue(i); + ExtendedClrTypeCode typeCode = MetaDataUtilsSmi.DetermineExtendedTypeCode(o); + SetCompatibleValue(sink, setters, i, metaData[i], o, typeCode, 0); + break; + case SqlDbType.Udt: + Debug.Assert(CanAccessSetterDirectly(metaData[i], ExtendedClrTypeCode.SqlBytes)); + SetBytes_FromRecord(sink, setters, i, metaData[i], record, 0); + break; + default: + Debug.Assert(false, "unsupported DbType:" + metaData[i].SqlDbType.ToString()); + throw ADP.NotSupported(); + } + } + } + } + + // spool a Stream into a scratch stream from the Smi interface and return it as a SqlStreamChars + internal static SqlStreamChars CopyIntoNewSmiScratchStreamChars(Stream source, SmiEventSink_Default sink, SmiContext context) + { + SqlClientWrapperSmiStreamChars dest = new(sink, context.GetScratchStream(sink)); + + int chunkSize; + if (source.CanSeek && __maxByteChunkSize > source.Length) + { + chunkSize = unchecked((int)source.Length); // unchecked cast is safe due to check on line above + } + else + { + chunkSize = __maxByteChunkSize; + } + + byte[] copyBuffer = new byte[chunkSize]; + int bytesRead; + while (0 != (bytesRead = source.Read(copyBuffer, 0, chunkSize))) + { + dest.Write(copyBuffer, 0, bytesRead); + } + dest.Flush(); + + // SQLBU 494334 + // Need to re-wind scratch stream to beginning before returning + dest.Seek(0, SeekOrigin.Begin); + + return dest; + } + + } +} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommandBuilder.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCommandBuilder.cs similarity index 53% rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommandBuilder.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCommandBuilder.cs index 317ee22ebb..cfac55e028 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommandBuilder.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlCommandBuilder.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.ComponentModel; using System.Data; using System.Data.Common; using System.Diagnostics; @@ -14,10 +15,11 @@ namespace Microsoft.Data.SqlClient { - /// + /// + [DesignerCategory()] public sealed class SqlCommandBuilder : DbCommandBuilder { - /// + /// public SqlCommandBuilder() : base() { GC.SuppressFinalize(this); @@ -25,14 +27,19 @@ public SqlCommandBuilder() : base() base.QuoteSuffix = "]"; } - /// + /// public SqlCommandBuilder(SqlDataAdapter adapter) : this() { DataAdapter = adapter; } - /// + /// /// SqlServer only supports CatalogLocation.Start + [ + Browsable(false), + EditorBrowsableAttribute(EditorBrowsableState.Never), + DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), + ] public override CatalogLocation CatalogLocation { get @@ -48,8 +55,13 @@ public override CatalogLocation CatalogLocation } } - /// + /// /// SqlServer only supports '.' + [ + Browsable(false), + EditorBrowsableAttribute(EditorBrowsableState.Never), + DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), + ] public override string CatalogSeparator { get @@ -65,8 +77,13 @@ public override string CatalogSeparator } } - /// - new public SqlDataAdapter DataAdapter + /// + [ + DefaultValue(null), + ResCategoryAttribute(StringsHelper.ResourceNames.DataCategory_Update), + ResDescriptionAttribute(StringsHelper.ResourceNames.SqlCommandBuilder_DataAdapter), + ] + public new SqlDataAdapter DataAdapter { get { @@ -78,8 +95,13 @@ public override string CatalogSeparator } } - /// + /// /// SqlServer only supports '.' + [ + Browsable(false), + EditorBrowsableAttribute(EditorBrowsableState.Never), + DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), + ] public override string QuotePrefix { get @@ -96,7 +118,12 @@ public override string QuotePrefix } } - /// + /// + [ + Browsable(false), + EditorBrowsableAttribute(EditorBrowsableState.Never), + DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), + ] public override string QuoteSuffix { get @@ -113,7 +140,12 @@ public override string QuoteSuffix } } - /// + /// + [ + Browsable(false), + EditorBrowsableAttribute(EditorBrowsableState.Never), + DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), + ] public override string SchemaSeparator { get @@ -134,31 +166,31 @@ private void SqlRowUpdatingHandler(object sender, SqlRowUpdatingEventArgs rueven base.RowUpdatingHandler(ruevent); } - /// - new public SqlCommand GetInsertCommand() + /// + public new SqlCommand GetInsertCommand() => (SqlCommand)base.GetInsertCommand(); - /// - new public SqlCommand GetInsertCommand(bool useColumnsForParameterNames) + /// + public new SqlCommand GetInsertCommand(bool useColumnsForParameterNames) => (SqlCommand)base.GetInsertCommand(useColumnsForParameterNames); - /// - new public SqlCommand GetUpdateCommand() + /// + public new SqlCommand GetUpdateCommand() => (SqlCommand)base.GetUpdateCommand(); - /// - new public SqlCommand GetUpdateCommand(bool useColumnsForParameterNames) + /// + public new SqlCommand GetUpdateCommand(bool useColumnsForParameterNames) => (SqlCommand)base.GetUpdateCommand(useColumnsForParameterNames); - /// - new public SqlCommand GetDeleteCommand() + /// + public new SqlCommand GetDeleteCommand() => (SqlCommand)base.GetDeleteCommand(); - /// - new public SqlCommand GetDeleteCommand(bool useColumnsForParameterNames) + /// + public new SqlCommand GetDeleteCommand(bool useColumnsForParameterNames) => (SqlCommand)base.GetDeleteCommand(useColumnsForParameterNames); - /// + /// protected override void ApplyParameterInfo(DbParameter parameter, DataRow datarow, StatementType statementType, bool whereClause) { SqlParameter p = (SqlParameter)parameter; @@ -190,15 +222,15 @@ protected override void ApplyParameterInfo(DbParameter parameter, DataRow dataro } } - /// + /// protected override string GetParameterName(int parameterOrdinal) => ("@p" + parameterOrdinal.ToString(CultureInfo.InvariantCulture)); - /// + /// protected override string GetParameterName(string parameterName) => ("@" + parameterName); - /// + /// protected override string GetParameterPlaceholder(int parameterOrdinal) => ("@p" + parameterOrdinal.ToString(CultureInfo.InvariantCulture)); @@ -212,18 +244,43 @@ private void ConsistentQuoteDelimiters(string quotePrefix, string quoteSuffix) } } - /// + /// public static void DeriveParameters(SqlCommand command) { +#if NETFRAMEWORK + SqlConnection.ExecutePermission.Demand(); +#endif if (null == command) { throw ADP.ArgumentNull(nameof(command)); } - +#if NETFRAMEWORK + TdsParser bestEffortCleanupTarget = null; +#endif RuntimeHelpers.PrepareConstrainedRegions(); try { - command.DeriveParameters(); +#if NETFRAMEWORK +#if DEBUG + TdsParser.ReliabilitySection tdsReliabilitySection = new TdsParser.ReliabilitySection(); + + RuntimeHelpers.PrepareConstrainedRegions(); + try { + tdsReliabilitySection.Start(); +#else + { +#endif // DEBUG + bestEffortCleanupTarget = SqlInternalConnection.GetBestEffortCleanupTarget(command.Connection); +#endif // NETFRAMEWORK + command.DeriveParameters(); +#if NETFRAMEWORK + } +#if DEBUG + finally { + tdsReliabilitySection.Stop(); + } +#endif // DEBUG +#endif // NETFRAMEWORK } catch (OutOfMemoryException e) { @@ -238,37 +295,44 @@ public static void DeriveParameters(SqlCommand command) catch (ThreadAbortException e) { command?.Connection?.Abort(e); +#if NETFRAMEWORK + SqlInternalConnection.BestEffortCleanup(bestEffortCleanupTarget); +#endif throw; } } - /// + /// protected override DataTable GetSchemaTable(DbCommand srcCommand) { SqlCommand sqlCommand = srcCommand as SqlCommand; SqlNotificationRequest notificationRequest = sqlCommand.Notification; - sqlCommand.Notification = null; +#if NETFRAMEWORK + bool notificationAutoEnlist = sqlCommand.NotificationAutoEnlist; + sqlCommand.NotificationAutoEnlist = false; +#endif try { - using (SqlDataReader dataReader = sqlCommand.ExecuteReader(CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo)) - { - return dataReader.GetSchemaTable(); - } + using SqlDataReader dataReader = sqlCommand.ExecuteReader(CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo); + return dataReader.GetSchemaTable(); } finally { sqlCommand.Notification = notificationRequest; +#if NETFRAMEWORK + sqlCommand.NotificationAutoEnlist = notificationAutoEnlist; +#endif } } - /// + /// protected override DbCommand InitializeCommand(DbCommand command) => (SqlCommand)base.InitializeCommand(command); - /// + /// public override string QuoteIdentifier(string unquotedIdentifier) { ADP.CheckArgumentNull(unquotedIdentifier, nameof(unquotedIdentifier)); @@ -278,7 +342,7 @@ public override string QuoteIdentifier(string unquotedIdentifier) return ADP.BuildQuotedString(quotePrefixLocal, quoteSuffixLocal, unquotedIdentifier); } - /// + /// protected override void SetRowUpdatingHandler(DbDataAdapter adapter) { Debug.Assert(adapter is SqlDataAdapter, "Adapter is not a SqlDataAdapter."); @@ -292,16 +356,15 @@ protected override void SetRowUpdatingHandler(DbDataAdapter adapter) } } - /// + /// public override string UnquoteIdentifier(string quotedIdentifier) { ADP.CheckArgumentNull(quotedIdentifier, nameof(quotedIdentifier)); - string unquotedIdentifier; string quoteSuffixLocal = QuoteSuffix; string quotePrefixLocal = QuotePrefix; ConsistentQuoteDelimiters(quotePrefixLocal, quoteSuffixLocal); // ignoring the return value because an unquoted source string is OK here - ADP.RemoveStringQuotes(quotePrefixLocal, quoteSuffixLocal, quotedIdentifier, out unquotedIdentifier); + ADP.RemoveStringQuotes(quotePrefixLocal, quoteSuffixLocal, quotedIdentifier, out string unquotedIdentifier); return unquotedIdentifier; } } diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionPoolGroupProviderInfo.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionPoolGroupProviderInfo.cs similarity index 70% rename from src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionPoolGroupProviderInfo.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionPoolGroupProviderInfo.cs index 24071a3db1..310aaee04d 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlConnectionPoolGroupProviderInfo.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlConnectionPoolGroupProviderInfo.cs @@ -2,46 +2,36 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Microsoft.Data.Common; +using System.Security; using Microsoft.Data.ProviderBase; namespace Microsoft.Data.SqlClient { - sealed internal class SqlConnectionPoolGroupProviderInfo : DbConnectionPoolGroupProviderInfo + internal sealed class SqlConnectionPoolGroupProviderInfo : DbConnectionPoolGroupProviderInfo { private string _alias; - private System.Security.PermissionSet _failoverPermissionSet; private string _failoverPartner; private bool _useFailoverPartner; +#if NETFRAMEWORK + private PermissionSet _failoverPermissionSet; +#endif internal SqlConnectionPoolGroupProviderInfo(SqlConnectionString connectionOptions) { // This is for the case where the user specified the failover partner - // in the connection string and we have not yet connected to get the + // in the connection string and we have not yet connected to get the // env change. _failoverPartner = connectionOptions.FailoverPartner; - if (ADP.IsEmpty(_failoverPartner)) + if (string.IsNullOrEmpty(_failoverPartner)) { _failoverPartner = null; } } - internal string FailoverPartner - { - get - { - return _failoverPartner; - } - } + internal string FailoverPartner => _failoverPartner; - internal bool UseFailoverPartner - { - get - { - return _useFailoverPartner; - } - } + internal bool UseFailoverPartner => _useFailoverPartner; internal void AliasCheck(string server) { @@ -55,7 +45,7 @@ internal void AliasCheck(string server) } else if (_alias != server) { - SqlClientEventSource.Log.TryTraceEvent(" alias change detected. Clearing PoolGroup"); + SqlClientEventSource.Log.TryTraceEvent("SqlConnectionPoolGroupProviderInfo.AliasCheck | Info | Alias change detected. Clearing PoolGroup."); base.PoolGroup.Clear(); _alias = server; } @@ -63,7 +53,40 @@ internal void AliasCheck(string server) } } - private System.Security.PermissionSet CreateFailoverPermission(SqlConnectionString userConnectionOptions, string actualFailoverPartner) + internal void FailoverCheck(bool actualUseFailoverPartner, SqlConnectionString userConnectionOptions, string actualFailoverPartner) + { + if (UseFailoverPartner != actualUseFailoverPartner) + { + SqlClientEventSource.Log.TryTraceEvent("SqlConnectionPoolGroupProviderInfo.FailoverCheck | Info | Failover detected. Failover partner '{0}'. Clearing PoolGroup", actualFailoverPartner); + base.PoolGroup.Clear(); + _useFailoverPartner = actualUseFailoverPartner; + } + // Only construct a new permission set when we're connecting to the + // primary data source, not the failover partner. + if (!_useFailoverPartner && _failoverPartner != actualFailoverPartner) + { + // NOTE: we optimistically generate the permission set to keep + // lock short, but we only do this when we get a new + // failover partner. + +#if NETFRAMEWORK + PermissionSet failoverPermissionSet = CreateFailoverPermission(userConnectionOptions, actualFailoverPartner); +#endif + lock (this) + { + if (_failoverPartner != actualFailoverPartner) + { + _failoverPartner = actualFailoverPartner; +#if NETFRAMEWORK + _failoverPermissionSet = failoverPermissionSet; +#endif + } + } + } + } + +#if NETFRAMEWORK + private PermissionSet CreateFailoverPermission(SqlConnectionString userConnectionOptions, string actualFailoverPartner) { string keywordToReplace; @@ -94,45 +117,13 @@ private System.Security.PermissionSet CreateFailoverPermission(SqlConnectionStri return (new SqlConnectionString(failoverConnectionString)).CreatePermissionSet(); } - internal void FailoverCheck(SqlInternalConnection connection, bool actualUseFailoverPartner, SqlConnectionString userConnectionOptions, string actualFailoverPartner) - { - if (UseFailoverPartner != actualUseFailoverPartner) - { - // TODO: will connections in progress somehow be active for two different datasources? - SqlClientEventSource.Log.TryTraceEvent(" Failover detected. failover partner='{0}'. Clearing PoolGroup", actualFailoverPartner); - - base.PoolGroup.Clear(); - _useFailoverPartner = actualUseFailoverPartner; - } - // Only construct a new permission set when we're connecting to the - // primary data source, not the failover partner. - if (!_useFailoverPartner && _failoverPartner != actualFailoverPartner) - { - // NOTE: we optimisitically generate the permission set to keep - // lock short, but we only do this when we get a new - // failover partner. - // TODO: it seems to me that being optimistic here may not be such a good idea; what if there are 100s of concurrent failovers? - - System.Security.PermissionSet failoverPermissionSet = CreateFailoverPermission(userConnectionOptions, actualFailoverPartner); - - lock (this) - { - if (_failoverPartner != actualFailoverPartner) - { - _failoverPartner = actualFailoverPartner; - _failoverPermissionSet = failoverPermissionSet; - } - } - } - } - internal void FailoverPermissionDemand() { if (_useFailoverPartner) { // Note that we only demand when there is a permission set, which only // happens once we've identified a failover situation in FailoverCheck - System.Security.PermissionSet failoverPermissionSet = _failoverPermissionSet; + PermissionSet failoverPermissionSet = _failoverPermissionSet; if (null != failoverPermissionSet) { // demand on pooled failover connections @@ -140,5 +131,6 @@ internal void FailoverPermissionDemand() } } } +#endif } } diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDependency.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlDependency.cs similarity index 76% rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDependency.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlDependency.cs index 23c8ad767c..80692b242d 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDependency.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlDependency.cs @@ -7,6 +7,13 @@ using System.Diagnostics; using System.Globalization; using System.Runtime.CompilerServices; +#if NETFRAMEWORK +using System.IO; +using System.Runtime.Remoting; +using System.Runtime.Serialization; +using System.Runtime.Versioning; +using System.Security.Permissions; +#endif using System.Text; using System.Threading; using System.Xml; @@ -16,14 +23,14 @@ namespace Microsoft.Data.SqlClient { - /// + /// public sealed class SqlDependency { // Private class encapsulating the user/identity information - either SQL Auth username or Windows identity. internal class IdentityUserNamePair { - private DbConnectionPoolIdentity _identity; - private string _userName; + private readonly DbConnectionPoolIdentity _identity; + private readonly string _userName; internal IdentityUserNamePair(DbConnectionPoolIdentity identity, string userName) { @@ -71,8 +78,7 @@ public override bool Equals(object value) public override int GetHashCode() { - int hashValue = 0; - + int hashValue; if (null != _identity) { hashValue = _identity.GetHashCode(); @@ -89,8 +95,8 @@ public override int GetHashCode() // Private class encapsulating the database, service info and hash logic. private class DatabaseServicePair { - private string _database; - private string _service; // Store the value, but don't use for equality or hashcode! + private readonly string _database; + private readonly string _service; // Store the value, but don't use for equality or hashcode! internal DatabaseServicePair(string database, string service) { @@ -125,21 +131,18 @@ public override bool Equals(object value) return result; } - public override int GetHashCode() - { - return _database.GetHashCode(); - } + public override int GetHashCode() => _database.GetHashCode(); } // Private class encapsulating the event and it's registered execution context. internal class EventContextPair { - private OnChangeEventHandler _eventHandler; - private ExecutionContext _context; - private SqlDependency _dependency; + private readonly OnChangeEventHandler _eventHandler; + private readonly ExecutionContext _context; + private readonly SqlDependency _dependency; private SqlNotificationEventArgs _args; - private static ContextCallback s_contextCallback = new ContextCallback(InvokeCallback); + private static readonly ContextCallback s_contextCallback = new(InvokeCallback); internal EventContextPair(OnChangeEventHandler eventHandler, SqlDependency dependency) { @@ -174,10 +177,7 @@ public override bool Equals(object value) return result; } - public override int GetHashCode() - { - return _eventHandler.GetHashCode(); - } + public override int GetHashCode() => _eventHandler.GetHashCode(); internal void Invoke(SqlNotificationEventArgs args) { @@ -192,62 +192,104 @@ private static void InvokeCallback(object eventContextPair) } } +#if NETFRAMEWORK + // Private Class to add ObjRef as DataContract + [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.RemotingConfiguration)] + [DataContract] + private class SqlClientObjRef + { + [DataMember] + private static ObjRef s_sqlObjRef; + internal static IRemotingTypeInfo s_typeInfo; + + private SqlClientObjRef() { } + + public SqlClientObjRef(SqlDependencyProcessDispatcher dispatcher) : base() + { + s_sqlObjRef = RemotingServices.Marshal(dispatcher); + s_typeInfo = s_sqlObjRef.TypeInfo; + } + + internal static bool CanCastToSqlDependencyProcessDispatcher() => s_typeInfo.CanCastTo(typeof(SqlDependencyProcessDispatcher), s_sqlObjRef); + + internal ObjRef GetObjRef() => s_sqlObjRef; + } +#endif + // Instance members // SqlNotificationRequest required state members // Only used for SqlDependency.Id. private readonly string _id = Guid.NewGuid().ToString() + ";" + s_appDomainKey; - private string _options; // Concat of service & db, in the form "service=x;local database=y". - private int _timeout; + private readonly string _options; // Concat of service & db, in the form "service=x;local database=y". + private readonly int _timeout; // Various SqlDependency required members private bool _dependencyFired = false; // We are required to implement our own event collection to preserve ExecutionContext on callback. - private List _eventList = new List(); - private object _eventHandlerLock = new object(); // Lock for event serialization. + private List _eventList = new(); + private readonly object _eventHandlerLock = new(); // Lock for event serialization. // Track the time that this dependency should time out. If the server didn't send a change // notification or a time-out before this point then the client will perform a client-side // timeout. private DateTime _expirationTime = DateTime.MaxValue; // Used for invalidation of dependencies based on which servers they rely upon. // It's possible we will over invalidate if unexpected server failure occurs (but not server down). - private List _serverList = new List(); + private readonly List _serverList = new(); // Static members - private static object s_startStopLock = new object(); + private static readonly object s_startStopLock = new(); private static readonly string s_appDomainKey = Guid.NewGuid().ToString(); // Hashtable containing all information to match from a server, user, database triple to the service started for that // triple. For each server, there can be N users. For each user, there can be N databases. For each server, user, // database, there can only be one service. - private static Dictionary>> s_serverUserHash = - new Dictionary>>(StringComparer.OrdinalIgnoreCase); + private static readonly Dictionary>> s_serverUserHash = + new(StringComparer.OrdinalIgnoreCase); private static SqlDependencyProcessDispatcher s_processDispatcher = null; +#if NETFRAMEWORK // The following two strings are used for AppDomain.CreateInstance. private static readonly string s_assemblyName = (typeof(SqlDependencyProcessDispatcher)).Assembly.FullName; private static readonly string s_typeName = (typeof(SqlDependencyProcessDispatcher)).FullName; +#endif - private static int _objectTypeCount; // EventSourceCounter counter - internal int ObjectID { get; } = Interlocked.Increment(ref _objectTypeCount); + // EventSource members + private static int s_objectTypeCount; // EventSourceCounter counter + internal int ObjectID { get; } = Interlocked.Increment(ref s_objectTypeCount); - /// + /// // Constructors +#if NETFRAMEWORK + [System.Security.Permissions.HostProtectionAttribute(ExternalThreading = true)] +#endif public SqlDependency() : this(null, null, SQL.SqlDependencyTimeoutDefault) { } - /// + /// +#if NETFRAMEWORK + [System.Security.Permissions.HostProtectionAttribute(ExternalThreading = true)] +#endif public SqlDependency(SqlCommand command) : this(command, null, SQL.SqlDependencyTimeoutDefault) { } - /// + /// +#if NETFRAMEWORK + [HostProtection(ExternalThreading = true)] +#endif public SqlDependency(SqlCommand command, string options, int timeout) { long scopeID = SqlClientEventSource.Log.TryNotificationScopeEnterEvent(" {0}, options: '{1}', timeout: '{2}'", ObjectID, options, timeout); try { +#if NETFRAMEWORK + if (InOutOfProcHelper.InProc) + { + throw SQL.SqlDepCannotBeCreatedInProc(); + } +#endif if (timeout < 0) { throw SQL.InvalidSqlDependencyTimeout(nameof(timeout)); @@ -269,10 +311,22 @@ public SqlDependency(SqlCommand command, string options, int timeout) } // Public Properties - /// +/// +#if NETFRAMEWORK + [ + ResCategoryAttribute(StringsHelper.ResourceNames.DataCategory_Data), + ResDescriptionAttribute(StringsHelper.ResourceNames.SqlDependency_HasChanges) + ] +#endif public bool HasChanges => _dependencyFired; - /// + /// +#if NETFRAMEWORK + [ + ResCategoryAttribute(StringsHelper.ResourceNames.DataCategory_Data), + ResDescriptionAttribute(StringsHelper.ResourceNames.SqlDependency_Id) + ] +#endif public string Id => _id; // Internal Properties @@ -288,7 +342,13 @@ public SqlDependency(SqlCommand command, string options, int timeout) internal int Timeout => _timeout; // Events - /// +/// +#if NETFRAMEWORK + [ + ResCategoryAttribute(StringsHelper.ResourceNames.DataCategory_Data), + ResDescriptionAttribute(StringsHelper.ResourceNames.SqlDependency_OnChange) + ] +#endif public event OnChangeEventHandler OnChange { // EventHandlers to be fired when dependency is notified. @@ -305,11 +365,13 @@ public event OnChangeEventHandler OnChange { if (_dependencyFired) { // If fired, fire the new event immediately. + SqlClientEventSource.Log.TryNotificationTraceEvent(" Dependency already fired, firing new event."); sqlNotificationEvent = new SqlNotificationEventArgs(SqlNotificationType.Subscribe, SqlNotificationInfo.AlreadyChanged, SqlNotificationSource.Client); } else { - EventContextPair pair = new EventContextPair(value, this); + SqlClientEventSource.Log.TryNotificationTraceEvent(" Dependency has not fired, adding new event."); + EventContextPair pair = new(value, this); if (!_eventList.Contains(pair)) { _eventList.Add(pair); @@ -339,7 +401,7 @@ public event OnChangeEventHandler OnChange { if (null != value) { - EventContextPair pair = new EventContextPair(value, this); + EventContextPair pair = new(value, this); lock (_eventHandlerLock) { int index = _eventList.IndexOf(pair); @@ -358,7 +420,13 @@ public event OnChangeEventHandler OnChange } // Public Methods - /// +/// +#if NETFRAMEWORK + [ + ResCategoryAttribute(StringsHelper.ResourceNames.DataCategory_Data), + ResDescriptionAttribute(StringsHelper.ResourceNames.SqlDependency_AddCommandDependency) + ] +#endif public void AddCommandDependency(SqlCommand command) { // Adds command to dependency collection so we automatically create the SqlNotificationsRequest object @@ -379,26 +447,134 @@ public void AddCommandDependency(SqlCommand command) } } +#if NETFRAMEWORK + [System.Security.Permissions.ReflectionPermission(System.Security.Permissions.SecurityAction.Assert, MemberAccess = true)] + private static ObjectHandle CreateProcessDispatcher(_AppDomain masterDomain) => masterDomain.CreateInstance(s_assemblyName, s_typeName); +#endif // Static Methods - public & internal - // Static Start/Stop methods - /// - public static bool Start(string connectionString) +#if NETFRAMEWORK + // Method to obtain AppDomain reference and then obtain the reference to the process wide dispatcher for + // Start() and Stop() method calls on the individual SqlDependency instances. + // SxS: this method retrieves the primary AppDomain stored in native library. Since each System.Data.dll has its own copy of native + // library, this call is safe in SxS + [ResourceExposure(ResourceScope.None)] + [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)] + private static void ObtainProcessDispatcher() + { + byte[] nativeStorage = SNINativeMethodWrapper.GetData(); + + if (nativeStorage == null) + { + SqlClientEventSource.Log.TryNotificationTraceEvent(" nativeStorage null, obtaining dispatcher AppDomain and creating ProcessDispatcher."); + +#if DEBUG // Possibly expensive, limit to debug. + SqlClientEventSource.Log.TryNotificationTraceEvent(" AppDomain.CurrentDomain.FriendlyName: {0}", AppDomain.CurrentDomain.FriendlyName); + +#endif // DEBUG + _AppDomain masterDomain = SNINativeMethodWrapper.GetDefaultAppDomain(); + + if (null != masterDomain) + { + ObjectHandle handle = CreateProcessDispatcher(masterDomain); + + if (null != handle) + { + SqlDependencyProcessDispatcher dependency = (SqlDependencyProcessDispatcher)handle.Unwrap(); + + if (null != dependency) + { + s_processDispatcher = dependency.SingletonProcessDispatcher; // Set to static instance. + + // Serialize and set in native. + using (MemoryStream stream = new()) + { + SqlClientObjRef objRef = new(s_processDispatcher); + DataContractSerializer serializer = new(objRef.GetType()); + GetSerializedObject(objRef, serializer, stream); + SNINativeMethodWrapper.SetData(stream.ToArray()); // Native will be forced to synchronize and not overwrite. + } + } + else + { + SqlClientEventSource.Log.TryNotificationTraceEvent(" ERROR - ObjectHandle.Unwrap returned null!"); + throw ADP.InternalError(ADP.InternalErrorCode.SqlDependencyObtainProcessDispatcherFailureObjectHandle); + } + } + else + { + SqlClientEventSource.Log.TryNotificationTraceEvent(" ERROR - AppDomain.CreateInstance returned null!"); + throw ADP.InternalError(ADP.InternalErrorCode.SqlDependencyProcessDispatcherFailureCreateInstance); + } + } + else + { + SqlClientEventSource.Log.TryNotificationTraceEvent(" ERROR - unable to obtain default AppDomain!"); + throw ADP.InternalError(ADP.InternalErrorCode.SqlDependencyProcessDispatcherFailureAppDomain); + } + } + else + { + SqlClientEventSource.Log.TryNotificationTraceEvent(" nativeStorage not null, obtaining existing dispatcher AppDomain and ProcessDispatcher."); + +#if DEBUG // Possibly expensive, limit to debug. + SqlClientEventSource.Log.TryNotificationTraceEvent(" AppDomain.CurrentDomain.FriendlyName: {0}", AppDomain.CurrentDomain.FriendlyName); +#endif // DEBUG + using (MemoryStream stream = new(nativeStorage)) + { + DataContractSerializer serializer = new(typeof(SqlClientObjRef)); + if (SqlClientObjRef.CanCastToSqlDependencyProcessDispatcher()) + { + // Deserialize and set for appdomain. + s_processDispatcher = GetDeserializedObject(serializer, stream); + } + else + { + throw new ArgumentException(Strings.SqlDependency_UnexpectedValueOnDeserialize); + } + SqlClientEventSource.Log.TryNotificationTraceEvent(" processDispatcher obtained, ID: {0}", s_processDispatcher.ObjectID); + } + } + } + + // --------------------------------------------------------- + // Static security asserted methods - limit scope of assert. + // --------------------------------------------------------- + + [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.SerializationFormatter)] + private static void GetSerializedObject(SqlClientObjRef objRef, DataContractSerializer serializer, MemoryStream stream) { - return Start(connectionString, null, true); + serializer.WriteObject(stream, objRef); } - /// - public static bool Start(string connectionString, string queue) + [SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.SerializationFormatter)] + private static SqlDependencyProcessDispatcher GetDeserializedObject(DataContractSerializer serializer, MemoryStream stream) { - return Start(connectionString, queue, false); + object refResult = serializer.ReadObject(stream); + var result = RemotingServices.Unmarshal((refResult as SqlClientObjRef).GetObjRef()); + return result as SqlDependencyProcessDispatcher; } +#endif // NETFRAMEWORK + // Static Start/Stop methods + /// + public static bool Start(string connectionString) => Start(connectionString, null, true); + + /// + public static bool Start(string connectionString, string queue) => Start(connectionString, queue, false); internal static bool Start(string connectionString, string queue, bool useDefaults) { long scopeID = SqlClientEventSource.Log.TryNotificationScopeEnterEvent(" AppDomainKey: '{0}', queue: '{1}'", AppDomainKey, queue); try { +#if NETFRAMEWORK + // The following code exists in Stop as well. It exists here to demand permissions as high in the stack + // as possible. + if (InOutOfProcHelper.InProc) + { + throw SQL.SqlDepCannotBeCreatedInProc(); + } +#endif if (string.IsNullOrEmpty(connectionString)) { if (null == connectionString) @@ -417,6 +593,16 @@ internal static bool Start(string connectionString, string queue, bool useDefaul queue = null; // Force to null - for proper hashtable comparison for default case. } +#if NETFRAMEWORK + // Create new connection options for demand on their connection string. We modify the connection string + // and assert on our modified string when we create the container. + SqlConnectionString connectionStringObject = new(connectionString); + connectionStringObject.DemandPermission(); + if (connectionStringObject.LocalDBInstance != null) + { + LocalDBAPI.DemandLocalDBPermissions(); + } +#endif // End duplicate Start/Stop logic. bool errorOccurred = false; @@ -428,7 +614,11 @@ internal static bool Start(string connectionString, string queue, bool useDefaul { if (null == s_processDispatcher) { // Ensure _processDispatcher reference is present - inside lock. +#if NETFRAMEWORK + ObtainProcessDispatcher(); +#else s_processDispatcher = SqlDependencyProcessDispatcher.SingletonProcessDispatcher; +#endif // NETFRAMEWORK } if (useDefaults) @@ -461,8 +651,8 @@ internal static bool Start(string connectionString, string queue, bool useDefaul { if (appDomainStart && !errorOccurred) { // If success, add to hashtable. - IdentityUserNamePair identityUser = new IdentityUserNamePair(identity, user); - DatabaseServicePair databaseService = new DatabaseServicePair(database, service); + IdentityUserNamePair identityUser = new(identity, user); + DatabaseServicePair databaseService = new(database, service); if (!AddToServerUserHash(server, identityUser, databaseService)) { try @@ -518,23 +708,25 @@ internal static bool Start(string connectionString, string queue, bool useDefaul } } - /// - public static bool Stop(string connectionString) - { - return Stop(connectionString, null, true, false); - } + /// + public static bool Stop(string connectionString) => Stop(connectionString, null, true, false); - /// - public static bool Stop(string connectionString, string queue) - { - return Stop(connectionString, queue, false, false); - } + /// + public static bool Stop(string connectionString, string queue) => Stop(connectionString, queue, false, false); internal static bool Stop(string connectionString, string queue, bool useDefaults, bool startFailed) { long scopeID = SqlClientEventSource.Log.TryNotificationScopeEnterEvent(" AppDomainKey: '{0}', queue: '{1}'", AppDomainKey, queue); try { +#if NETFRAMEWORK + // The following code exists in Stop as well. It exists here to demand permissions as high in the stack + // as possible. + if (InOutOfProcHelper.InProc) + { + throw SQL.SqlDepCannotBeCreatedInProc(); + } +#endif if (string.IsNullOrEmpty(connectionString)) { if (null == connectionString) @@ -553,6 +745,16 @@ internal static bool Stop(string connectionString, string queue, bool useDefault queue = null; // Force to null - for proper hashtable comparison for default case. } +#if NETFRAMEWORK + // Create new connection options for demand on their connection string. We modify the connection string + // and assert on our modified string when we create the container. + SqlConnectionString connectionStringObject = new(connectionString); + connectionStringObject.DemandPermission(); + if (connectionStringObject.LocalDBInstance != null) + { + LocalDBAPI.DemandLocalDBPermissions(); + } +#endif // End duplicate Start/Stop logic. bool result = false; @@ -592,8 +794,8 @@ internal static bool Stop(string connectionString, string queue, bool useDefault if (appDomainStop && !startFailed) { // If success, remove from hashtable. Debug.Assert(!string.IsNullOrEmpty(server) && !string.IsNullOrEmpty(database), "Server or Database null/Empty upon successful Stop()!"); - IdentityUserNamePair identityUser = new IdentityUserNamePair(identity, user); - DatabaseServicePair databaseService = new DatabaseServicePair(database, service); + IdentityUserNamePair identityUser = new(identity, user); + DatabaseServicePair databaseService = new(database, service); RemoveFromServerUserHash(server, identityUser, databaseService); } } @@ -810,7 +1012,7 @@ internal static string GetDefaultComposedOptions(string server, string failoverS databaseList = identityDatabaseHash[identityUser]; } - DatabaseServicePair pair = new DatabaseServicePair(database, null); + DatabaseServicePair pair = new(database, null); DatabaseServicePair resultingPair = null; int index = databaseList.IndexOf(pair); if (index != -1) @@ -869,6 +1071,7 @@ internal void AddToServerList(string server) int index = _serverList.BinarySearch(server, StringComparer.OrdinalIgnoreCase); if (0 > index) { // If less than 0, item was not found in list. + SqlClientEventSource.Log.TryNotificationTraceEvent(" Server not present in hashtable, adding server: '{0}'.", server); index = ~index; // BinarySearch returns the 2's compliment of where the item should be inserted to preserver a sorted list after insertion. _serverList.Insert(index, server); @@ -972,6 +1175,7 @@ internal void StartTimer(SqlNotificationRequest notificationRequest) { if (_expirationTime == DateTime.MaxValue) { + SqlClientEventSource.Log.TryNotificationTraceEvent(" We've timed out, executing logic."); int seconds = SQL.SqlDependencyServerTimeout; if (0 != _timeout) { @@ -1074,7 +1278,7 @@ private string ComputeCommandHash(string connectionString, SqlCommand command) // All types should properly support a .ToString for the values except // byte[], char[], and XmlReader. - StringBuilder builder = new StringBuilder(); + StringBuilder builder = new(); // add the Connection string and the Command text builder.AppendFormat("{0};{1}", connectionString, command.CommandText); diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlEnums.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlEnums.cs similarity index 54% rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlEnums.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlEnums.cs index cdf9a4799e..6cc1bcaf35 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlEnums.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlEnums.cs @@ -6,6 +6,9 @@ using System.Collections.Generic; using System.Data; using System.Data.Common; +#if NETFRAMEWORK +using System.Data.OleDb; +#endif using System.Data.SqlTypes; using System.Diagnostics; using System.Globalization; @@ -54,22 +57,22 @@ internal sealed class MetaType public MetaType(byte precision, byte scale, int fixedLength, bool isFixed, bool isLong, bool isPlp, byte tdsType, byte nullableTdsType, string typeName, Type classType, Type sqlType, SqlDbType sqldbType, DbType dbType, byte propBytes) { - this.Precision = precision; - this.Scale = scale; - this.FixedLength = fixedLength; - this.IsFixed = isFixed; - this.IsLong = isLong; - this.IsPlp = isPlp; - - this.TDSType = tdsType; - this.NullableType = nullableTdsType; - this.TypeName = typeName; - this.SqlDbType = sqldbType; - this.DbType = dbType; - - this.ClassType = classType; - this.SqlType = sqlType; - this.PropBytes = propBytes; + Precision = precision; + Scale = scale; + FixedLength = fixedLength; + IsFixed = isFixed; + IsLong = isLong; + IsPlp = isPlp; + + TDSType = tdsType; + NullableType = nullableTdsType; + TypeName = typeName; + SqlDbType = sqldbType; + DbType = dbType; + + ClassType = classType; + SqlType = sqlType; + PropBytes = propBytes; IsAnsiType = _IsAnsiType(sqldbType); IsBinType = _IsBinType(sqldbType); @@ -86,93 +89,66 @@ public MetaType(byte precision, byte scale, int fixedLength, bool isFixed, bool } // properties should be inlined so there should be no perf penalty for using these accessor functions - public int TypeId - { // partial length prefixed (xml, nvarchar(max),...) - get { return 0; } - } + public int TypeId => 0; // partial length prefixed (xml, nvarchar(max),...) - private static bool _IsAnsiType(SqlDbType type) - { - return (type == SqlDbType.Char || - type == SqlDbType.VarChar || - type == SqlDbType.Text); - } + private static bool _IsAnsiType(SqlDbType type) => + type == SqlDbType.Char || type == SqlDbType.VarChar || type == SqlDbType.Text; // is this type size expressed as count of characters or bytes? - private static bool _IsSizeInCharacters(SqlDbType type) - { - return (type == SqlDbType.NChar || - type == SqlDbType.NVarChar || - type == SqlDbType.Xml || - type == SqlDbType.NText); - } - - private static bool _IsCharType(SqlDbType type) - { - return (type == SqlDbType.NChar || - type == SqlDbType.NVarChar || - type == SqlDbType.NText || - type == SqlDbType.Char || - type == SqlDbType.VarChar || - type == SqlDbType.Text || - type == SqlDbType.Xml); - } - - private static bool _IsNCharType(SqlDbType type) - { - return (type == SqlDbType.NChar || - type == SqlDbType.NVarChar || - type == SqlDbType.NText || - type == SqlDbType.Xml); - } - - private static bool _IsBinType(SqlDbType type) - { - return (type == SqlDbType.Image || - type == SqlDbType.Binary || - type == SqlDbType.VarBinary || - type == SqlDbType.Timestamp || - type == SqlDbType.Udt || - (int)type == 24 /*SqlSmallVarBinary*/); - } - - private static bool _Is70Supported(SqlDbType type) - { - return ((type != SqlDbType.BigInt) && ((int)type > 0) && - ((int)type <= (int)SqlDbType.VarChar)); - } - - private static bool _Is80Supported(SqlDbType type) - { - return ((int)type >= 0 && - ((int)type <= (int)SqlDbType.Variant)); - } - - private static bool _Is90Supported(SqlDbType type) - { - return _Is80Supported(type) || - SqlDbType.Xml == type || - SqlDbType.Udt == type; - } - - private static bool _Is100Supported(SqlDbType type) - { - return _Is90Supported(type) || - SqlDbType.Date == type || - SqlDbType.Time == type || - SqlDbType.DateTime2 == type || - SqlDbType.DateTimeOffset == type; - } - - private static bool _IsNewKatmaiType(SqlDbType type) - { - return SqlDbType.Structured == type; - } - - internal static bool _IsVarTime(SqlDbType type) - { - return (type == SqlDbType.Time || type == SqlDbType.DateTime2 || type == SqlDbType.DateTimeOffset); - } + private static bool _IsSizeInCharacters(SqlDbType type) => + type == SqlDbType.NChar || + type == SqlDbType.NVarChar || + type == SqlDbType.Xml || + type == SqlDbType.NText; + + private static bool _IsCharType(SqlDbType type) => + type == SqlDbType.NChar || + type == SqlDbType.NVarChar || + type == SqlDbType.NText || + type == SqlDbType.Char || + type == SqlDbType.VarChar || + type == SqlDbType.Text || + type == SqlDbType.Xml; + + private static bool _IsNCharType(SqlDbType type) => + type == SqlDbType.NChar || + type == SqlDbType.NVarChar || + type == SqlDbType.NText || + type == SqlDbType.Xml; + + private static bool _IsBinType(SqlDbType type) => + type == SqlDbType.Image || + type == SqlDbType.Binary || + type == SqlDbType.VarBinary || + type == SqlDbType.Timestamp || + type == SqlDbType.Udt || + (int)type == 24 /*SqlSmallVarBinary*/; + + private static bool _Is70Supported(SqlDbType type) => + type != SqlDbType.BigInt && + (int)type > 0 && + (int)type <= (int)SqlDbType.VarChar; + + private static bool _Is80Supported(SqlDbType type) => + (int)type >= 0 && + (int)type <= (int)SqlDbType.Variant; + + private static bool _Is90Supported(SqlDbType type) => + _Is80Supported(type) || + SqlDbType.Xml == type || + SqlDbType.Udt == type; + + private static bool _Is100Supported(SqlDbType type) => + _Is90Supported(type) || + SqlDbType.Date == type || + SqlDbType.Time == type || + SqlDbType.DateTime2 == type || + SqlDbType.DateTimeOffset == type; + + private static bool _IsNewKatmaiType(SqlDbType type) => SqlDbType.Structured == type; + + internal static bool _IsVarTime(SqlDbType type) => + type == SqlDbType.Time || type == SqlDbType.DateTime2 || type == SqlDbType.DateTimeOffset; // // map SqlDbType to MetaType class @@ -263,95 +239,55 @@ internal static MetaType GetMetaTypeFromSqlDbType(SqlDbType target, bool isMulti internal static MetaType GetMetaTypeFromDbType(DbType target) { // if we can't map it, we need to throw - switch (target) + return target switch { - case DbType.AnsiString: - return s_metaVarChar; - case DbType.AnsiStringFixedLength: - return s_metaChar; - case DbType.Binary: - return MetaVarBinary; - case DbType.Byte: - return s_metaTinyInt; - case DbType.Boolean: - return s_metaBit; - case DbType.Currency: - return s_metaMoney; - case DbType.Date: - return s_metaDate; - case DbType.DateTime: - return s_metaDateTime; - case DbType.Decimal: - return MetaDecimal; - case DbType.Double: - return s_metaFloat; - case DbType.Guid: - return s_metaUniqueId; - case DbType.Int16: - return s_metaSmallInt; - case DbType.Int32: - return s_metaInt; - case DbType.Int64: - return s_metaBigInt; - case DbType.Object: - return s_metaVariant; - case DbType.Single: - return s_metaReal; - case DbType.String: - return MetaNVarChar; - case DbType.StringFixedLength: - return s_metaNChar; - case DbType.Time: - return MetaTime; - case DbType.Xml: - return MetaXml; - case DbType.DateTime2: - return s_metaDateTime2; - case DbType.DateTimeOffset: - return MetaDateTimeOffset; - case DbType.SByte: // unsupported - case DbType.UInt16: - case DbType.UInt32: - case DbType.UInt64: - case DbType.VarNumeric: - default: - throw ADP.DbTypeNotSupported(target, typeof(SqlDbType)); // no direct mapping, error out - } + DbType.AnsiString => s_metaVarChar, + DbType.AnsiStringFixedLength => s_metaChar, + DbType.Binary => MetaVarBinary, + DbType.Byte => s_metaTinyInt, + DbType.Boolean => s_metaBit, + DbType.Currency => s_metaMoney, + DbType.Date => s_metaDate, + DbType.DateTime => s_metaDateTime, + DbType.Decimal => MetaDecimal, + DbType.Double => s_metaFloat, + DbType.Guid => s_metaUniqueId, + DbType.Int16 => s_metaSmallInt, + DbType.Int32 => s_metaInt, + DbType.Int64 => s_metaBigInt, + DbType.Object => s_metaVariant, + DbType.Single => s_metaReal, + DbType.String => MetaNVarChar, + DbType.StringFixedLength => s_metaNChar, + DbType.Time => MetaTime, + DbType.Xml => MetaXml, + DbType.DateTime2 => s_metaDateTime2, + DbType.DateTimeOffset => MetaDateTimeOffset, + // unsupported + _ => throw ADP.DbTypeNotSupported(target, typeof(SqlDbType)),// no direct mapping, error out + }; } internal static MetaType GetMaxMetaTypeFromMetaType(MetaType mt) { // if we can't map it, we need to throw - switch (mt.SqlDbType) + return mt.SqlDbType switch { - case SqlDbType.VarBinary: - case SqlDbType.Binary: - return MetaMaxVarBinary; - case SqlDbType.VarChar: - case SqlDbType.Char: - return MetaMaxVarChar; - case SqlDbType.NVarChar: - case SqlDbType.NChar: - return MetaMaxNVarChar; - case SqlDbType.Udt: - return s_metaMaxUdt; - default: - return mt; - } + SqlDbType.VarBinary or SqlDbType.Binary => MetaMaxVarBinary, + SqlDbType.VarChar or SqlDbType.Char => MetaMaxVarChar, + SqlDbType.NVarChar or SqlDbType.NChar => MetaMaxNVarChar, + SqlDbType.Udt => s_metaMaxUdt, + _ => mt, + }; } // // map COM+ Type to MetaType class // - internal static MetaType GetMetaTypeFromType(Type dataType) - { - return GetMetaTypeFromValue(dataType, null, false, true); - } + internal static MetaType GetMetaTypeFromType(Type dataType) => GetMetaTypeFromValue(dataType, null, false, true); - internal static MetaType GetMetaTypeFromValue(object value, bool streamAllowed = true) - { - return GetMetaTypeFromValue(value.GetType(), value, true, streamAllowed); - } + internal static MetaType GetMetaTypeFromValue(object value, bool streamAllowed = true) => + GetMetaTypeFromValue(value.GetType(), value, true, streamAllowed); private static MetaType GetMetaTypeFromValue(Type dataType, object value, bool inferLen, bool streamAllowed) { @@ -363,6 +299,7 @@ private static MetaType GetMetaTypeFromValue(Type dataType, object value, bool i if (dataType == typeof(byte[])) { // Must not default to image if inferLen is false + // MDAC 90455 if (!inferLen || ((byte[])value).Length <= TdsEnums.TYPE_SIZE_LIMIT) { return MetaVarBinary; @@ -389,7 +326,7 @@ private static MetaType GetMetaTypeFromValue(Type dataType, object value, bool i else if (dataType == typeof(SqlBytes)) return MetaVarBinary; else if (dataType == typeof(SqlChars)) - return MetaNVarChar; + return MetaNVarChar; // MDAC 87587 else if (dataType == typeof(SqlDateTime)) return s_metaDateTime; else if (dataType == typeof(SqlDouble)) @@ -414,7 +351,7 @@ private static MetaType GetMetaTypeFromValue(Type dataType, object value, bool i { return ((inferLen && !((SqlString)value).IsNull) ? PromoteStringType(((SqlString)value).Value) - : MetaNVarChar); + : MetaNVarChar); // MDAC 87587 } else if (dataType == typeof(IEnumerable) || dataType == typeof(DataTable)) { @@ -561,40 +498,55 @@ internal static object GetComValueFromSqlVariant(object sqlVal) if (ADP.IsNull(sqlVal)) return comVal; - if (sqlVal is SqlSingle) - comVal = ((SqlSingle)sqlVal).Value; - else if (sqlVal is SqlString) - comVal = ((SqlString)sqlVal).Value; - else if (sqlVal is SqlDouble) - comVal = ((SqlDouble)sqlVal).Value; - else if (sqlVal is SqlBinary) - comVal = ((SqlBinary)sqlVal).Value; - else if (sqlVal is SqlGuid) - comVal = ((SqlGuid)sqlVal).Value; - else if (sqlVal is SqlBoolean) - comVal = ((SqlBoolean)sqlVal).Value; - else if (sqlVal is SqlByte) - comVal = ((SqlByte)sqlVal).Value; - else if (sqlVal is SqlInt16) - comVal = ((SqlInt16)sqlVal).Value; - else if (sqlVal is SqlInt32) - comVal = ((SqlInt32)sqlVal).Value; - else if (sqlVal is SqlInt64) - comVal = ((SqlInt64)sqlVal).Value; - else if (sqlVal is SqlDecimal) - comVal = ((SqlDecimal)sqlVal).Value; - else if (sqlVal is SqlDateTime) - comVal = ((SqlDateTime)sqlVal).Value; - else if (sqlVal is SqlMoney) - comVal = ((SqlMoney)sqlVal).Value; - else if (sqlVal is SqlXml) - comVal = ((SqlXml)sqlVal).Value; - else + switch (sqlVal) { - AssertIsUserDefinedTypeInstance(sqlVal, "unknown SqlType class stored in sqlVal"); + case SqlSingle: + comVal = ((SqlSingle)sqlVal).Value; + break; + case SqlString: + comVal = ((SqlString)sqlVal).Value; + break; + case SqlDouble: + comVal = ((SqlDouble)sqlVal).Value; + break; + case SqlBinary: + comVal = ((SqlBinary)sqlVal).Value; + break; + case SqlGuid: + comVal = ((SqlGuid)sqlVal).Value; + break; + case SqlBoolean: + comVal = ((SqlBoolean)sqlVal).Value; + break; + case SqlByte: + comVal = ((SqlByte)sqlVal).Value; + break; + case SqlInt16: + comVal = ((SqlInt16)sqlVal).Value; + break; + case SqlInt32: + comVal = ((SqlInt32)sqlVal).Value; + break; + case SqlInt64: + comVal = ((SqlInt64)sqlVal).Value; + break; + case SqlDecimal: + comVal = ((SqlDecimal)sqlVal).Value; + break; + case SqlDateTime: + comVal = ((SqlDateTime)sqlVal).Value; + break; + case SqlMoney: + comVal = ((SqlMoney)sqlVal).Value; + break; + case SqlXml: + comVal = ((SqlXml)sqlVal).Value; + break; + default: + AssertIsUserDefinedTypeInstance(sqlVal, "unknown SqlType class stored in sqlVal"); + break; } - return comVal; } @@ -616,7 +568,7 @@ internal static object GetComValueFromSqlVariant(object sqlVal) private static void AssertIsUserDefinedTypeInstance(object sqlValue, string failedAssertMessage) { Type type = sqlValue.GetType(); - Microsoft.Data.SqlClient.Server.SqlUserDefinedTypeAttribute[] attributes = (Microsoft.Data.SqlClient.Server.SqlUserDefinedTypeAttribute[])type.GetCustomAttributes(typeof(Microsoft.Data.SqlClient.Server.SqlUserDefinedTypeAttribute), true); + SqlUserDefinedTypeAttribute[] attributes = (SqlUserDefinedTypeAttribute[])type.GetCustomAttributes(typeof(SqlUserDefinedTypeAttribute), true); Debug.Assert(attributes.Length > 0, failedAssertMessage); } @@ -628,53 +580,169 @@ internal static object GetSqlValueFromComVariant(object comVal) object sqlVal = null; if ((null != comVal) && (DBNull.Value != comVal)) { - if (comVal is float) - sqlVal = new SqlSingle((float)comVal); - else if (comVal is string) - sqlVal = new SqlString((string)comVal); - else if (comVal is double) - sqlVal = new SqlDouble((double)comVal); - else if (comVal is byte[]) - sqlVal = new SqlBinary((byte[])comVal); - else if (comVal is char) - sqlVal = new SqlString(((char)comVal).ToString()); - else if (comVal is char[]) - sqlVal = new SqlChars((char[])comVal); - else if (comVal is System.Guid) - sqlVal = new SqlGuid((Guid)comVal); - else if (comVal is bool) - sqlVal = new SqlBoolean((bool)comVal); - else if (comVal is byte) - sqlVal = new SqlByte((byte)comVal); - else if (comVal is short) - sqlVal = new SqlInt16((short)comVal); - else if (comVal is int) - sqlVal = new SqlInt32((int)comVal); - else if (comVal is long) - sqlVal = new SqlInt64((long)comVal); - else if (comVal is decimal) - sqlVal = new SqlDecimal((decimal)comVal); - else if (comVal is DateTime) + switch (comVal) { - // devnote: Do not use with SqlDbType.Date and SqlDbType.DateTime2. See comment at top of method. - sqlVal = new SqlDateTime((DateTime)comVal); - } - else if (comVal is XmlReader) - sqlVal = new SqlXml((XmlReader)comVal); - else if (comVal is TimeSpan || comVal is DateTimeOffset) - sqlVal = comVal; + case float: + sqlVal = new SqlSingle((float)comVal); + break; + case string: + sqlVal = new SqlString((string)comVal); + break; + case double: + sqlVal = new SqlDouble((double)comVal); + break; + case byte[]: + sqlVal = new SqlBinary((byte[])comVal); + break; + case char: + sqlVal = new SqlString(((char)comVal).ToString()); + break; + case char[]: + sqlVal = new SqlChars((char[])comVal); + break; + case System.Guid: + sqlVal = new SqlGuid((Guid)comVal); + break; + case bool: + sqlVal = new SqlBoolean((bool)comVal); + break; + case byte: + sqlVal = new SqlByte((byte)comVal); + break; + case short: + sqlVal = new SqlInt16((short)comVal); + break; + case int: + sqlVal = new SqlInt32((int)comVal); + break; + case long: + sqlVal = new SqlInt64((long)comVal); + break; + case decimal: + sqlVal = new SqlDecimal((decimal)comVal); + break; + case DateTime: + // devnote: Do not use with SqlDbType.Date and SqlDbType.DateTime2. See comment at top of method. + sqlVal = new SqlDateTime((DateTime)comVal); + break; + case XmlReader: + sqlVal = new SqlXml((XmlReader)comVal); + break; + case TimeSpan: + case DateTimeOffset: + sqlVal = comVal; + break; + default: #if DEBUG - else - Debug.Fail("unknown SqlType class stored in sqlVal"); + Debug.Fail("unknown SqlType class stored in sqlVal"); #endif + break; + } } return sqlVal; } internal static SqlDbType GetSqlDbTypeFromOleDbType(short dbType, string typeName) { +#if NETFRAMEWORK + SqlDbType sqlType = SqlDbType.Variant; + switch ((OleDbType)dbType) + { + case OleDbType.BigInt: + sqlType = SqlDbType.BigInt; + break; + case OleDbType.Boolean: + sqlType = SqlDbType.Bit; + break; + case OleDbType.Char: + case OleDbType.VarChar: + // these guys are ambiguous - server sends over DBTYPE_STR in both cases + sqlType = (typeName == MetaTypeName.CHAR) ? SqlDbType.Char : SqlDbType.VarChar; + break; + case OleDbType.Currency: + sqlType = (typeName == MetaTypeName.SMALLMONEY) ? SqlDbType.SmallMoney : SqlDbType.Money; + break; + case OleDbType.Date: + case OleDbType.DBTimeStamp: + case OleDbType.Filetime: + sqlType = typeName switch + { + MetaTypeName.SMALLDATETIME => SqlDbType.SmallDateTime, + MetaTypeName.DATETIME2 => SqlDbType.DateTime2, + _ => SqlDbType.DateTime, + }; + break; + case OleDbType.Decimal: + case OleDbType.Numeric: + sqlType = SqlDbType.Decimal; + break; + case OleDbType.Double: + sqlType = SqlDbType.Float; + break; + case OleDbType.Guid: + sqlType = SqlDbType.UniqueIdentifier; + break; + case OleDbType.Integer: + sqlType = SqlDbType.Int; + break; + case OleDbType.LongVarBinary: + sqlType = SqlDbType.Image; + break; + case OleDbType.LongVarChar: + sqlType = SqlDbType.Text; + break; + case OleDbType.LongVarWChar: + sqlType = SqlDbType.NText; + break; + case OleDbType.Single: + sqlType = SqlDbType.Real; + break; + case OleDbType.SmallInt: + case OleDbType.UnsignedSmallInt: + sqlType = SqlDbType.SmallInt; + break; + case OleDbType.TinyInt: + case OleDbType.UnsignedTinyInt: + sqlType = SqlDbType.TinyInt; + break; + case OleDbType.VarBinary: + case OleDbType.Binary: + sqlType = (typeName == MetaTypeName.BINARY) ? SqlDbType.Binary : SqlDbType.VarBinary; + break; + case OleDbType.Variant: + sqlType = SqlDbType.Variant; + break; + case OleDbType.VarWChar: + case OleDbType.WChar: + case OleDbType.BSTR: + // these guys are ambiguous - server sends over DBTYPE_WSTR in both cases + // BSTR is always assumed to be NVARCHAR + sqlType = (typeName == MetaTypeName.NCHAR) ? SqlDbType.NChar : SqlDbType.NVarChar; + break; + case OleDbType.DBDate: // Date + sqlType = SqlDbType.Date; + break; + case (OleDbType)132: // Udt + sqlType = SqlDbType.Udt; + break; + case (OleDbType)141: // Xml + sqlType = SqlDbType.Xml; + break; + case (OleDbType)145: // Time + sqlType = SqlDbType.Time; + break; + case (OleDbType)146: // DateTimeOffset + sqlType = SqlDbType.DateTimeOffset; + break; + // TODO: Handle Structured types for derive parameters + default: + break; // no direct mapping, just use SqlDbType.Variant; + } + return sqlType; +#else // OleDbTypes not supported return SqlDbType.Variant; +#endif // NETFRAMEWORK } internal static MetaType GetSqlDataType(int tdsType, uint userType, int length) @@ -773,148 +841,108 @@ internal static MetaType GetSqlDataType(int tdsType, uint userType, int length) } } - internal static MetaType GetDefaultMetaType() - { - return MetaNVarChar; - } + internal static MetaType GetDefaultMetaType() => MetaNVarChar; // Converts an XmlReader into String internal static string GetStringFromXml(XmlReader xmlreader) { - SqlXml sxml = new SqlXml(xmlreader); + SqlXml sxml = new(xmlreader); return sxml.Value; } - private static readonly MetaType s_metaBigInt = new MetaType - (19, 255, 8, true, false, false, TdsEnums.SQLINT8, TdsEnums.SQLINTN, MetaTypeName.BIGINT, typeof(long), typeof(SqlInt64), SqlDbType.BigInt, DbType.Int64, 0); + private static readonly MetaType s_metaBigInt = new(19, 255, 8, true, false, false, TdsEnums.SQLINT8, TdsEnums.SQLINTN, MetaTypeName.BIGINT, typeof(long), typeof(SqlInt64), SqlDbType.BigInt, DbType.Int64, 0); - private static readonly MetaType s_metaFloat = new MetaType - (15, 255, 8, true, false, false, TdsEnums.SQLFLT8, TdsEnums.SQLFLTN, MetaTypeName.FLOAT, typeof(double), typeof(SqlDouble), SqlDbType.Float, DbType.Double, 0); + private static readonly MetaType s_metaFloat = new(15, 255, 8, true, false, false, TdsEnums.SQLFLT8, TdsEnums.SQLFLTN, MetaTypeName.FLOAT, typeof(double), typeof(SqlDouble), SqlDbType.Float, DbType.Double, 0); - private static readonly MetaType s_metaReal = new MetaType - (7, 255, 4, true, false, false, TdsEnums.SQLFLT4, TdsEnums.SQLFLTN, MetaTypeName.REAL, typeof(float), typeof(SqlSingle), SqlDbType.Real, DbType.Single, 0); + private static readonly MetaType s_metaReal = new(7, 255, 4, true, false, false, TdsEnums.SQLFLT4, TdsEnums.SQLFLTN, MetaTypeName.REAL, typeof(float), typeof(SqlSingle), SqlDbType.Real, DbType.Single, 0); // MetaBinary has two bytes of properties for binary and varbinary // 2 byte maxlen - private static readonly MetaType s_metaBinary = new MetaType - (255, 255, -1, false, false, false, TdsEnums.SQLBIGBINARY, TdsEnums.SQLBIGBINARY, MetaTypeName.BINARY, typeof(byte[]), typeof(SqlBinary), SqlDbType.Binary, DbType.Binary, 2); + private static readonly MetaType s_metaBinary = new(255, 255, -1, false, false, false, TdsEnums.SQLBIGBINARY, TdsEnums.SQLBIGBINARY, MetaTypeName.BINARY, typeof(byte[]), typeof(SqlBinary), SqlDbType.Binary, DbType.Binary, 2); // Syntactic sugar for the user...timestamps are 8-byte fixed length binary columns - private static readonly MetaType s_metaTimestamp = new MetaType - (255, 255, -1, false, false, false, TdsEnums.SQLBIGBINARY, TdsEnums.SQLBIGBINARY, MetaTypeName.TIMESTAMP, typeof(byte[]), typeof(SqlBinary), SqlDbType.Timestamp, DbType.Binary, 2); + private static readonly MetaType s_metaTimestamp = new(255, 255, -1, false, false, false, TdsEnums.SQLBIGBINARY, TdsEnums.SQLBIGBINARY, MetaTypeName.TIMESTAMP, typeof(byte[]), typeof(SqlBinary), SqlDbType.Timestamp, DbType.Binary, 2); - internal static readonly MetaType MetaVarBinary = new MetaType - (255, 255, -1, false, false, false, TdsEnums.SQLBIGVARBINARY, TdsEnums.SQLBIGVARBINARY, MetaTypeName.VARBINARY, typeof(byte[]), typeof(SqlBinary), SqlDbType.VarBinary, DbType.Binary, 2); + internal static readonly MetaType MetaVarBinary = new(255, 255, -1, false, false, false, TdsEnums.SQLBIGVARBINARY, TdsEnums.SQLBIGVARBINARY, MetaTypeName.VARBINARY, typeof(byte[]), typeof(SqlBinary), SqlDbType.VarBinary, DbType.Binary, 2); - internal static readonly MetaType MetaMaxVarBinary = new MetaType - (255, 255, -1, false, true, true, TdsEnums.SQLBIGVARBINARY, TdsEnums.SQLBIGVARBINARY, MetaTypeName.VARBINARY, typeof(byte[]), typeof(SqlBinary), SqlDbType.VarBinary, DbType.Binary, 2); + internal static readonly MetaType MetaMaxVarBinary = new(255, 255, -1, false, true, true, TdsEnums.SQLBIGVARBINARY, TdsEnums.SQLBIGVARBINARY, MetaTypeName.VARBINARY, typeof(byte[]), typeof(SqlBinary), SqlDbType.VarBinary, DbType.Binary, 2); // We have an internal type for smallvarbinarys stored on TdsEnums. We // store on TdsEnums instead of SqlDbType because we do not want to expose // this type to the user. - private static readonly MetaType s_metaSmallVarBinary = new MetaType - (255, 255, -1, false, false, false, TdsEnums.SQLVARBINARY, TdsEnums.SQLBIGBINARY, "", typeof(byte[]), typeof(SqlBinary), TdsEnums.SmallVarBinary, DbType.Binary, 2); + private static readonly MetaType s_metaSmallVarBinary = new(255, 255, -1, false, false, false, TdsEnums.SQLVARBINARY, TdsEnums.SQLBIGBINARY, "", typeof(byte[]), typeof(SqlBinary), TdsEnums.SmallVarBinary, DbType.Binary, 2); - internal static readonly MetaType MetaImage = new MetaType - (255, 255, -1, false, true, false, TdsEnums.SQLIMAGE, TdsEnums.SQLIMAGE, MetaTypeName.IMAGE, typeof(byte[]), typeof(SqlBinary), SqlDbType.Image, DbType.Binary, 0); + internal static readonly MetaType MetaImage = new(255, 255, -1, false, true, false, TdsEnums.SQLIMAGE, TdsEnums.SQLIMAGE, MetaTypeName.IMAGE, typeof(byte[]), typeof(SqlBinary), SqlDbType.Image, DbType.Binary, 0); - private static readonly MetaType s_metaBit = new MetaType - (255, 255, 1, true, false, false, TdsEnums.SQLBIT, TdsEnums.SQLBITN, MetaTypeName.BIT, typeof(bool), typeof(SqlBoolean), SqlDbType.Bit, DbType.Boolean, 0); + private static readonly MetaType s_metaBit = new(255, 255, 1, true, false, false, TdsEnums.SQLBIT, TdsEnums.SQLBITN, MetaTypeName.BIT, typeof(bool), typeof(SqlBoolean), SqlDbType.Bit, DbType.Boolean, 0); - private static readonly MetaType s_metaTinyInt = new MetaType - (3, 255, 1, true, false, false, TdsEnums.SQLINT1, TdsEnums.SQLINTN, MetaTypeName.TINYINT, typeof(byte), typeof(SqlByte), SqlDbType.TinyInt, DbType.Byte, 0); + private static readonly MetaType s_metaTinyInt = new(3, 255, 1, true, false, false, TdsEnums.SQLINT1, TdsEnums.SQLINTN, MetaTypeName.TINYINT, typeof(byte), typeof(SqlByte), SqlDbType.TinyInt, DbType.Byte, 0); - private static readonly MetaType s_metaSmallInt = new MetaType - (5, 255, 2, true, false, false, TdsEnums.SQLINT2, TdsEnums.SQLINTN, MetaTypeName.SMALLINT, typeof(short), typeof(SqlInt16), SqlDbType.SmallInt, DbType.Int16, 0); + private static readonly MetaType s_metaSmallInt = new(5, 255, 2, true, false, false, TdsEnums.SQLINT2, TdsEnums.SQLINTN, MetaTypeName.SMALLINT, typeof(short), typeof(SqlInt16), SqlDbType.SmallInt, DbType.Int16, 0); - private static readonly MetaType s_metaInt = new MetaType - (10, 255, 4, true, false, false, TdsEnums.SQLINT4, TdsEnums.SQLINTN, MetaTypeName.INT, typeof(int), typeof(SqlInt32), SqlDbType.Int, DbType.Int32, 0); + private static readonly MetaType s_metaInt = new(10, 255, 4, true, false, false, TdsEnums.SQLINT4, TdsEnums.SQLINTN, MetaTypeName.INT, typeof(int), typeof(SqlInt32), SqlDbType.Int, DbType.Int32, 0); // MetaVariant has seven bytes of properties for MetaChar and MetaVarChar // 5 byte tds collation // 2 byte maxlen - private static readonly MetaType s_metaChar = new MetaType - (255, 255, -1, false, false, false, TdsEnums.SQLBIGCHAR, TdsEnums.SQLBIGCHAR, MetaTypeName.CHAR, typeof(string), typeof(SqlString), SqlDbType.Char, DbType.AnsiStringFixedLength, 7); + private static readonly MetaType s_metaChar = new(255, 255, -1, false, false, false, TdsEnums.SQLBIGCHAR, TdsEnums.SQLBIGCHAR, MetaTypeName.CHAR, typeof(string), typeof(SqlString), SqlDbType.Char, DbType.AnsiStringFixedLength, 7); - private static readonly MetaType s_metaVarChar = new MetaType - (255, 255, -1, false, false, false, TdsEnums.SQLBIGVARCHAR, TdsEnums.SQLBIGVARCHAR, MetaTypeName.VARCHAR, typeof(string), typeof(SqlString), SqlDbType.VarChar, DbType.AnsiString, 7); + private static readonly MetaType s_metaVarChar = new(255, 255, -1, false, false, false, TdsEnums.SQLBIGVARCHAR, TdsEnums.SQLBIGVARCHAR, MetaTypeName.VARCHAR, typeof(string), typeof(SqlString), SqlDbType.VarChar, DbType.AnsiString, 7); - internal static readonly MetaType MetaMaxVarChar = new MetaType - (255, 255, -1, false, true, true, TdsEnums.SQLBIGVARCHAR, TdsEnums.SQLBIGVARCHAR, MetaTypeName.VARCHAR, typeof(string), typeof(SqlString), SqlDbType.VarChar, DbType.AnsiString, 7); + internal static readonly MetaType MetaMaxVarChar = new(255, 255, -1, false, true, true, TdsEnums.SQLBIGVARCHAR, TdsEnums.SQLBIGVARCHAR, MetaTypeName.VARCHAR, typeof(string), typeof(SqlString), SqlDbType.VarChar, DbType.AnsiString, 7); - internal static readonly MetaType MetaText = new MetaType - (255, 255, -1, false, true, false, TdsEnums.SQLTEXT, TdsEnums.SQLTEXT, MetaTypeName.TEXT, typeof(string), typeof(SqlString), SqlDbType.Text, DbType.AnsiString, 0); + internal static readonly MetaType MetaText = new(255, 255, -1, false, true, false, TdsEnums.SQLTEXT, TdsEnums.SQLTEXT, MetaTypeName.TEXT, typeof(string), typeof(SqlString), SqlDbType.Text, DbType.AnsiString, 0); // MetaVariant has seven bytes of properties for MetaNChar and MetaNVarChar // 5 byte tds collation // 2 byte maxlen - private static readonly MetaType s_metaNChar = new MetaType - (255, 255, -1, false, false, false, TdsEnums.SQLNCHAR, TdsEnums.SQLNCHAR, MetaTypeName.NCHAR, typeof(string), typeof(SqlString), SqlDbType.NChar, DbType.StringFixedLength, 7); + private static readonly MetaType s_metaNChar = new(255, 255, -1, false, false, false, TdsEnums.SQLNCHAR, TdsEnums.SQLNCHAR, MetaTypeName.NCHAR, typeof(string), typeof(SqlString), SqlDbType.NChar, DbType.StringFixedLength, 7); - internal static readonly MetaType MetaNVarChar = new MetaType - (255, 255, -1, false, false, false, TdsEnums.SQLNVARCHAR, TdsEnums.SQLNVARCHAR, MetaTypeName.NVARCHAR, typeof(string), typeof(SqlString), SqlDbType.NVarChar, DbType.String, 7); + internal static readonly MetaType MetaNVarChar = new(255, 255, -1, false, false, false, TdsEnums.SQLNVARCHAR, TdsEnums.SQLNVARCHAR, MetaTypeName.NVARCHAR, typeof(string), typeof(SqlString), SqlDbType.NVarChar, DbType.String, 7); - internal static readonly MetaType MetaMaxNVarChar = new MetaType - (255, 255, -1, false, true, true, TdsEnums.SQLNVARCHAR, TdsEnums.SQLNVARCHAR, MetaTypeName.NVARCHAR, typeof(string), typeof(SqlString), SqlDbType.NVarChar, DbType.String, 7); + internal static readonly MetaType MetaMaxNVarChar = new(255, 255, -1, false, true, true, TdsEnums.SQLNVARCHAR, TdsEnums.SQLNVARCHAR, MetaTypeName.NVARCHAR, typeof(string), typeof(SqlString), SqlDbType.NVarChar, DbType.String, 7); - internal static readonly MetaType MetaNText = new MetaType - (255, 255, -1, false, true, false, TdsEnums.SQLNTEXT, TdsEnums.SQLNTEXT, MetaTypeName.NTEXT, typeof(string), typeof(SqlString), SqlDbType.NText, DbType.String, 7); + internal static readonly MetaType MetaNText = new(255, 255, -1, false, true, false, TdsEnums.SQLNTEXT, TdsEnums.SQLNTEXT, MetaTypeName.NTEXT, typeof(string), typeof(SqlString), SqlDbType.NText, DbType.String, 7); // MetaVariant has two bytes of properties for numeric/decimal types // 1 byte precision // 1 byte scale - internal static readonly MetaType MetaDecimal = new MetaType - (38, 4, 17, true, false, false, TdsEnums.SQLNUMERICN, TdsEnums.SQLNUMERICN, MetaTypeName.DECIMAL, typeof(decimal), typeof(SqlDecimal), SqlDbType.Decimal, DbType.Decimal, 2); + internal static readonly MetaType MetaDecimal = new(38, 4, 17, true, false, false, TdsEnums.SQLNUMERICN, TdsEnums.SQLNUMERICN, MetaTypeName.DECIMAL, typeof(decimal), typeof(SqlDecimal), SqlDbType.Decimal, DbType.Decimal, 2); - internal static readonly MetaType MetaXml = new MetaType - (255, 255, -1, false, true, true, TdsEnums.SQLXMLTYPE, TdsEnums.SQLXMLTYPE, MetaTypeName.XML, typeof(string), typeof(SqlXml), SqlDbType.Xml, DbType.Xml, 0); + internal static readonly MetaType MetaXml = new(255, 255, -1, false, true, true, TdsEnums.SQLXMLTYPE, TdsEnums.SQLXMLTYPE, MetaTypeName.XML, typeof(string), typeof(SqlXml), SqlDbType.Xml, DbType.Xml, 0); - private static readonly MetaType s_metaDateTime = new MetaType - (23, 3, 8, true, false, false, TdsEnums.SQLDATETIME, TdsEnums.SQLDATETIMN, MetaTypeName.DATETIME, typeof(System.DateTime), typeof(SqlDateTime), SqlDbType.DateTime, DbType.DateTime, 0); + private static readonly MetaType s_metaDateTime = new(23, 3, 8, true, false, false, TdsEnums.SQLDATETIME, TdsEnums.SQLDATETIMN, MetaTypeName.DATETIME, typeof(System.DateTime), typeof(SqlDateTime), SqlDbType.DateTime, DbType.DateTime, 0); - private static readonly MetaType s_metaSmallDateTime = new MetaType - (16, 0, 4, true, false, false, TdsEnums.SQLDATETIM4, TdsEnums.SQLDATETIMN, MetaTypeName.SMALLDATETIME, typeof(System.DateTime), typeof(SqlDateTime), SqlDbType.SmallDateTime, DbType.DateTime, 0); + private static readonly MetaType s_metaSmallDateTime = new(16, 0, 4, true, false, false, TdsEnums.SQLDATETIM4, TdsEnums.SQLDATETIMN, MetaTypeName.SMALLDATETIME, typeof(System.DateTime), typeof(SqlDateTime), SqlDbType.SmallDateTime, DbType.DateTime, 0); - private static readonly MetaType s_metaMoney = new MetaType - (19, 255, 8, true, false, false, TdsEnums.SQLMONEY, TdsEnums.SQLMONEYN, MetaTypeName.MONEY, typeof(decimal), typeof(SqlMoney), SqlDbType.Money, DbType.Currency, 0); + private static readonly MetaType s_metaMoney = new(19, 255, 8, true, false, false, TdsEnums.SQLMONEY, TdsEnums.SQLMONEYN, MetaTypeName.MONEY, typeof(decimal), typeof(SqlMoney), SqlDbType.Money, DbType.Currency, 0); - private static readonly MetaType s_metaSmallMoney = new MetaType - (10, 255, 4, true, false, false, TdsEnums.SQLMONEY4, TdsEnums.SQLMONEYN, MetaTypeName.SMALLMONEY, typeof(decimal), typeof(SqlMoney), SqlDbType.SmallMoney, DbType.Currency, 0); + private static readonly MetaType s_metaSmallMoney = new(10, 255, 4, true, false, false, TdsEnums.SQLMONEY4, TdsEnums.SQLMONEYN, MetaTypeName.SMALLMONEY, typeof(decimal), typeof(SqlMoney), SqlDbType.SmallMoney, DbType.Currency, 0); - private static readonly MetaType s_metaUniqueId = new MetaType - (255, 255, 16, true, false, false, TdsEnums.SQLUNIQUEID, TdsEnums.SQLUNIQUEID, MetaTypeName.ROWGUID, typeof(System.Guid), typeof(SqlGuid), SqlDbType.UniqueIdentifier, DbType.Guid, 0); + private static readonly MetaType s_metaUniqueId = new(255, 255, 16, true, false, false, TdsEnums.SQLUNIQUEID, TdsEnums.SQLUNIQUEID, MetaTypeName.ROWGUID, typeof(System.Guid), typeof(SqlGuid), SqlDbType.UniqueIdentifier, DbType.Guid, 0); - private static readonly MetaType s_metaVariant = new MetaType - (255, 255, -1, true, false, false, TdsEnums.SQLVARIANT, TdsEnums.SQLVARIANT, MetaTypeName.VARIANT, typeof(object), typeof(object), SqlDbType.Variant, DbType.Object, 0); + private static readonly MetaType s_metaVariant = new(255, 255, -1, true, false, false, TdsEnums.SQLVARIANT, TdsEnums.SQLVARIANT, MetaTypeName.VARIANT, typeof(object), typeof(object), SqlDbType.Variant, DbType.Object, 0); - internal static readonly MetaType MetaUdt = new MetaType - (255, 255, -1, false, false, true, TdsEnums.SQLUDT, TdsEnums.SQLUDT, MetaTypeName.UDT, typeof(object), typeof(object), SqlDbType.Udt, DbType.Object, 0); + internal static readonly MetaType MetaUdt = new(255, 255, -1, false, false, true, TdsEnums.SQLUDT, TdsEnums.SQLUDT, MetaTypeName.UDT, typeof(object), typeof(object), SqlDbType.Udt, DbType.Object, 0); - private static readonly MetaType s_metaMaxUdt = new MetaType - (255, 255, -1, false, true, true, TdsEnums.SQLUDT, TdsEnums.SQLUDT, MetaTypeName.UDT, typeof(object), typeof(object), SqlDbType.Udt, DbType.Object, 0); + private static readonly MetaType s_metaMaxUdt = new(255, 255, -1, false, true, true, TdsEnums.SQLUDT, TdsEnums.SQLUDT, MetaTypeName.UDT, typeof(object), typeof(object), SqlDbType.Udt, DbType.Object, 0); - private static readonly MetaType s_metaTable = new MetaType - (255, 255, -1, false, false, false, TdsEnums.SQLTABLE, TdsEnums.SQLTABLE, MetaTypeName.TABLE, typeof(IEnumerable), typeof(IEnumerable), SqlDbType.Structured, DbType.Object, 0); + private static readonly MetaType s_metaTable = new(255, 255, -1, false, false, false, TdsEnums.SQLTABLE, TdsEnums.SQLTABLE, MetaTypeName.TABLE, typeof(IEnumerable), typeof(IEnumerable), SqlDbType.Structured, DbType.Object, 0); - private static readonly MetaType s_metaSUDT = new MetaType - (255, 255, -1, false, false, false, TdsEnums.SQLVOID, TdsEnums.SQLVOID, "", typeof(SqlDataRecord), typeof(SqlDataRecord), SqlDbType.Structured, DbType.Object, 0); + private static readonly MetaType s_metaSUDT = new(255, 255, -1, false, false, false, TdsEnums.SQLVOID, TdsEnums.SQLVOID, "", typeof(SqlDataRecord), typeof(SqlDataRecord), SqlDbType.Structured, DbType.Object, 0); - private static readonly MetaType s_metaDate = new MetaType - (255, 255, 3, true, false, false, TdsEnums.SQLDATE, TdsEnums.SQLDATE, MetaTypeName.DATE, typeof(System.DateTime), typeof(System.DateTime), SqlDbType.Date, DbType.Date, 0); + private static readonly MetaType s_metaDate = new(255, 255, 3, true, false, false, TdsEnums.SQLDATE, TdsEnums.SQLDATE, MetaTypeName.DATE, typeof(System.DateTime), typeof(System.DateTime), SqlDbType.Date, DbType.Date, 0); - internal static readonly MetaType MetaTime = new MetaType - (255, 7, -1, false, false, false, TdsEnums.SQLTIME, TdsEnums.SQLTIME, MetaTypeName.TIME, typeof(System.TimeSpan), typeof(System.TimeSpan), SqlDbType.Time, DbType.Time, 1); + internal static readonly MetaType MetaTime = new(255, 7, -1, false, false, false, TdsEnums.SQLTIME, TdsEnums.SQLTIME, MetaTypeName.TIME, typeof(System.TimeSpan), typeof(System.TimeSpan), SqlDbType.Time, DbType.Time, 1); - private static readonly MetaType s_metaDateTime2 = new MetaType - (255, 7, -1, false, false, false, TdsEnums.SQLDATETIME2, TdsEnums.SQLDATETIME2, MetaTypeName.DATETIME2, typeof(System.DateTime), typeof(System.DateTime), SqlDbType.DateTime2, DbType.DateTime2, 1); + private static readonly MetaType s_metaDateTime2 = new(255, 7, -1, false, false, false, TdsEnums.SQLDATETIME2, TdsEnums.SQLDATETIME2, MetaTypeName.DATETIME2, typeof(System.DateTime), typeof(System.DateTime), SqlDbType.DateTime2, DbType.DateTime2, 1); - internal static readonly MetaType MetaDateTimeOffset = new MetaType - (255, 7, -1, false, false, false, TdsEnums.SQLDATETIMEOFFSET, TdsEnums.SQLDATETIMEOFFSET, MetaTypeName.DATETIMEOFFSET, typeof(System.DateTimeOffset), typeof(System.DateTimeOffset), SqlDbType.DateTimeOffset, DbType.DateTimeOffset, 1); + internal static readonly MetaType MetaDateTimeOffset = new(255, 7, -1, false, false, false, TdsEnums.SQLDATETIMEOFFSET, TdsEnums.SQLDATETIMEOFFSET, MetaTypeName.DATETIMEOFFSET, typeof(System.DateTimeOffset), typeof(System.DateTimeOffset), SqlDbType.DateTimeOffset, DbType.DateTimeOffset, 1); public static TdsDateTime FromDateTime(DateTime dateTime, byte cb) { SqlDateTime sqlDateTime; - TdsDateTime tdsDateTime = new TdsDateTime(); + TdsDateTime tdsDateTime = new(); Debug.Assert(cb == 8 || cb == 4, "Invalid date time size!"); diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlErrorCollection.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlErrorCollection.cs new file mode 100644 index 0000000000..4684747627 --- /dev/null +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlErrorCollection.cs @@ -0,0 +1,50 @@ +// 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; +using System.Collections.Generic; +using System.ComponentModel; + +namespace Microsoft.Data.SqlClient +{ + /// + [Serializable, ListBindable(false)] + public sealed class SqlErrorCollection : ICollection + { + // Ideally this would be typed as List, but that would make the non-generic + // CopyTo behave differently than the full framework (which uses ArrayList), throwing + // ArgumentException instead of the expected InvalidCastException for incompatible types. + // Instead, we use List, which makes the non-generic CopyTo behave like + // ArrayList.CopyTo. + private readonly List _errors = new List(); + + internal SqlErrorCollection() { } + + /// + public void CopyTo(Array array, int index) => ((ICollection)_errors).CopyTo(array, index); + + /// + public void CopyTo(SqlError[] array, int index) => _errors.CopyTo(array, index); + + /// + public int Count => _errors.Count; + + /// + // MDAC 68481 + object ICollection.SyncRoot => this; + + /// + // MDAC 68481 + bool ICollection.IsSynchronized => false; + + /// + public SqlError this[int index] => (SqlError)_errors[index]; + + /// + public IEnumerator GetEnumerator() => _errors.GetEnumerator(); + + internal void Add(SqlError error) => _errors.Add(error); + } +} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlException.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlException.cs similarity index 62% rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlException.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlException.cs index 2c50c5a3d7..bbc8670aa8 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlException.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlException.cs @@ -12,7 +12,7 @@ namespace Microsoft.Data.SqlClient { - /// + /// [Serializable] public sealed partial class SqlException : System.Data.Common.DbException { @@ -20,7 +20,10 @@ public sealed partial class SqlException : System.Data.Common.DbException private const string RoutingDestinationKey = "RoutingDestination"; private const int SqlExceptionHResult = unchecked((int)0x80131904); - private SqlErrorCollection _errors; + private readonly SqlErrorCollection _errors; +#if NETFRAMEWORK + [System.Runtime.Serialization.OptionalFieldAttribute(VersionAdded = 4)] +#endif private Guid _clientConnectionId = Guid.Empty; private SqlException(string message, SqlErrorCollection errorCollection, Exception innerException, Guid conId) : base(message, innerException) @@ -32,6 +35,9 @@ private SqlException(string message, SqlErrorCollection errorCollection, Excepti private SqlException(SerializationInfo si, StreamingContext sc) : base(si, sc) { +#if NETFRAMEWORK + _errors = (SqlErrorCollection)si.GetValue("Errors", typeof(SqlErrorCollection)); +#endif HResult = SqlExceptionHResult; foreach (SerializationEntry siEntry in si) { @@ -43,7 +49,7 @@ private SqlException(SerializationInfo si, StreamingContext sc) : base(si, sc) } } - /// + /// public override void GetObjectData(SerializationInfo si, StreamingContext context) { base.GetObjectData(si, context); @@ -62,75 +68,41 @@ public override void GetObjectData(SerializationInfo si, StreamingContext contex } } - /// + /// // runtime will call even if private... - public SqlErrorCollection Errors - { - get - { - if (_errors == null) - { - _errors = new SqlErrorCollection(); - } - return _errors; - } - } +#if NETFRAMEWORK + [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] +#endif + public SqlErrorCollection Errors => _errors ?? new SqlErrorCollection(); - /// - public Guid ClientConnectionId - { - get - { - return _clientConnectionId; - } - } + /// + public Guid ClientConnectionId => _clientConnectionId; - /// - public byte Class - { - get { return Errors.Count > 0 ? Errors[0].Class : default; } - } + /// + public byte Class => Errors.Count > 0 ? Errors[0].Class : default; - /// - public int LineNumber - { - get { return Errors.Count > 0 ? Errors[0].LineNumber : default; } - } + /// + public int LineNumber => Errors.Count > 0 ? Errors[0].LineNumber : default; - /// - public int Number - { - get { return Errors.Count > 0 ? Errors[0].Number : default; } - } + /// + public int Number => Errors.Count > 0 ? Errors[0].Number : default; - /// - public string Procedure - { - get { return Errors.Count > 0 ? Errors[0].Procedure : default; } - } + /// + public string Procedure => Errors.Count > 0 ? Errors[0].Procedure : default; - /// - public string Server - { - get { return Errors.Count > 0 ? Errors[0].Server : default; } - } + /// + public string Server => Errors.Count > 0 ? Errors[0].Server : default; - /// - public byte State - { - get { return Errors.Count > 0 ? Errors[0].State : default; } - } + /// + public byte State => Errors.Count > 0 ? Errors[0].State : default; - /// - override public string Source - { - get { return TdsEnums.SQL_PROVIDER_NAME; } - } + /// + override public string Source => TdsEnums.SQL_PROVIDER_NAME; - /// + /// public override string ToString() { - StringBuilder sb = new StringBuilder(base.ToString()); + StringBuilder sb = new(base.ToString()); sb.AppendLine(); sb.AppendFormat(SQLMessage.ExClientConnectionId(), _clientConnectionId); @@ -166,7 +138,7 @@ internal static SqlException CreateException(SqlErrorCollection errorCollection, internal static SqlException CreateException(SqlErrorCollection errorCollection, string serverVersion, SqlInternalConnectionTds internalConnection, Exception innerException = null) { Guid connectionId = (internalConnection == null) ? Guid.Empty : internalConnection._clientConnectionId; - var exception = CreateException(errorCollection, serverVersion, connectionId, innerException); + SqlException exception = CreateException(errorCollection, serverVersion, connectionId, innerException); if (internalConnection != null) { @@ -188,7 +160,7 @@ internal static SqlException CreateException(SqlErrorCollection errorCollection, { Debug.Assert(null != errorCollection && errorCollection.Count > 0, "no errorCollection?"); - StringBuilder message = new StringBuilder(); + StringBuilder message = new(); for (int i = 0; i < errorCollection.Count; i++) { if (i > 0) @@ -203,7 +175,7 @@ internal static SqlException CreateException(SqlErrorCollection errorCollection, innerException = new Win32Exception(errorCollection[0].Win32ErrorCode); } - SqlException exception = new SqlException(message.ToString(), errorCollection, innerException, conId); + SqlException exception = new(message.ToString(), errorCollection, innerException, conId); exception.Data.Add("HelpLink.ProdName", "Microsoft SQL Server"); @@ -221,11 +193,16 @@ internal static SqlException CreateException(SqlErrorCollection errorCollection, internal SqlException InternalClone() { - SqlException exception = new SqlException(Message, _errors, InnerException, _clientConnectionId); - if (this.Data != null) - foreach (DictionaryEntry entry in this.Data) + SqlException exception = new(Message, _errors, InnerException, _clientConnectionId); + if (Data != null) + { + foreach (DictionaryEntry entry in Data) + { exception.Data.Add(entry.Key, entry.Value); - exception._doNotReconnect = this._doNotReconnect; + } + } + + exception._doNotReconnect = _doNotReconnect; return exception; } diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlNotificationEventArgs.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlNotificationEventArgs.cs new file mode 100644 index 0000000000..6e7c6d4ca7 --- /dev/null +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlNotificationEventArgs.cs @@ -0,0 +1,35 @@ +// 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; + +namespace Microsoft.Data.SqlClient +{ + /// + public class SqlNotificationEventArgs : EventArgs + { + private readonly SqlNotificationType _type; + private readonly SqlNotificationInfo _info; + private readonly SqlNotificationSource _source; + + /// + public SqlNotificationEventArgs(SqlNotificationType type, SqlNotificationInfo info, SqlNotificationSource source) + { + _info = info; + _source = source; + _type = type; + } + + /// + public SqlNotificationType Type => _type; + + /// + public SqlNotificationInfo Info => _info; + + /// + public SqlNotificationSource Source => _source; + + internal static SqlNotificationEventArgs s_notifyError = new(SqlNotificationType.Subscribe, SqlNotificationInfo.Error, SqlNotificationSource.Object); + } +} diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlReferenceCollection.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlReferenceCollection.cs similarity index 100% rename from src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlReferenceCollection.cs rename to src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlReferenceCollection.cs diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs index 5ad2d85615..bf08250e83 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlConnectionStringBuilderTest.cs @@ -88,6 +88,7 @@ public void ConnectionStringTests(string connectionString) } [Theory] + [InlineData("Connection Reset = false")] [InlineData("Context Connection = false")] [InlineData("Network Library = dbmssocn")] [InlineData("Network = dbnmpntw")] diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs index c1a0c9a235..2d809934e1 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/DataCommon/DataTestUtility.cs @@ -163,25 +163,24 @@ static DataTestUtility() } } - public static IEnumerable ConnectionStrings + public static IEnumerable ConnectionStrings => GetConnectionStrings(withEnclave: true); + + public static IEnumerable GetConnectionStrings(bool withEnclave) { - get + if (!string.IsNullOrEmpty(TCPConnectionString)) { - if (!string.IsNullOrEmpty(TCPConnectionString)) - { - yield return TCPConnectionString; - } - // Named Pipes are not supported on Unix platform and for Azure DB - if (Environment.OSVersion.Platform != PlatformID.Unix && IsNotAzureServer() && !string.IsNullOrEmpty(NPConnectionString)) - { - yield return NPConnectionString; - } - if (EnclaveEnabled) + yield return TCPConnectionString; + } + // Named Pipes are not supported on Unix platform and for Azure DB + if (Environment.OSVersion.Platform != PlatformID.Unix && IsNotAzureServer() && !string.IsNullOrEmpty(NPConnectionString)) + { + yield return NPConnectionString; + } + if (withEnclave && EnclaveEnabled) + { + foreach (var connStr in AEConnStrings) { - foreach (var connStr in AEConnStrings) - { - yield return connStr; - } + yield return connStr; } } } diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/RetryLogicTestHelper.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/RetryLogicTestHelper.cs index d72c9f3d4c..ba83e9b22a 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/RetryLogicTestHelper.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/RetryLogicTestHelper.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Reflection; using System.Text; using System.Text.RegularExpressions; @@ -75,13 +74,14 @@ private static readonly HashSet s_defaultTransientErrors 207 // invalid column name }; - internal static readonly string s_ExceedErrMsgPattern = SystemDataResourceManager.Instance.SqlRetryLogic_RetryExceeded; - internal static readonly string s_CancelErrMsgPattern = SystemDataResourceManager.Instance.SqlRetryLogic_RetryCanceled; + internal static readonly string s_exceedErrMsgPattern = SystemDataResourceManager.Instance.SqlRetryLogic_RetryExceeded; + internal static readonly string s_cancelErrMsgPattern = SystemDataResourceManager.Instance.SqlRetryLogic_RetryCanceled; public static IEnumerable GetConnectionStrings() { var builder = new SqlConnectionStringBuilder(); - foreach (var cnnString in DataTestUtility.ConnectionStrings) + + foreach (var cnnString in DataTestUtility.GetConnectionStrings(withEnclave: false)) { builder.Clear(); builder.ConnectionString = cnnString; @@ -150,8 +150,8 @@ public static IEnumerable GetConnectionAndRetryStrategyLockedTable(int public static IEnumerable GetNoneRetriableCondition() { - yield return new object[] { DataTestUtility.TCPConnectionString, null}; - yield return new object[] { DataTestUtility.TCPConnectionString, SqlConfigurableRetryFactory.CreateNoneRetryProvider()}; + yield return new object[] { DataTestUtility.TCPConnectionString, null }; + yield return new object[] { DataTestUtility.TCPConnectionString, SqlConfigurableRetryFactory.CreateNoneRetryProvider() }; } private static IEnumerable GetRetryStrategies(SqlRetryLogicOption retryLogicOption) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlCommandReliabilityTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlCommandReliabilityTest.cs index ff46122f81..9e3ed81af4 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlCommandReliabilityTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlCommandReliabilityTest.cs @@ -13,12 +13,12 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests { public class SqlCommandReliabilityTest { - private readonly string _exceedErrMsgPattern = RetryLogicTestHelper.s_ExceedErrMsgPattern; - private readonly string _cancelErrMsgPattern = RetryLogicTestHelper.s_CancelErrMsgPattern; + private readonly string _exceedErrMsgPattern = RetryLogicTestHelper.s_exceedErrMsgPattern; + private readonly string _cancelErrMsgPattern = RetryLogicTestHelper.s_cancelErrMsgPattern; #region Sync - [Theory] - [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCommand), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper))] + [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] + [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCommand), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] public void RetryExecuteFail(string cnnString, SqlRetryLogicBaseProvider provider) { int numberOfTries = provider.RetryLogic.NumberOfTries; @@ -62,8 +62,8 @@ public void RetryExecuteFail(string cnnString, SqlRetryLogicBaseProvider provide } } - [Theory] - [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCommand), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper))] + [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] + [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCommand), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] public void RetryExecuteCancel(string cnnString, SqlRetryLogicBaseProvider provider) { int numberOfTries = provider.RetryLogic.NumberOfTries; @@ -108,8 +108,8 @@ public void RetryExecuteCancel(string cnnString, SqlRetryLogicBaseProvider provi } [ActiveIssue(14588)] - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsNotAzureSynapse))] - [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCommand), parameters: new object[] { 5 }, MemberType = typeof(RetryLogicTestHelper))] + [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsNotAzureSynapse), nameof(DataTestUtility.AreConnStringsSetup))] + [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCommand), parameters: new object[] { 5 }, MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] public void RetryExecuteWithTransScope(string cnnString, SqlRetryLogicBaseProvider provider) { int numberOfTries = provider.RetryLogic.NumberOfTries; @@ -144,8 +144,8 @@ public void RetryExecuteWithTransScope(string cnnString, SqlRetryLogicBaseProvid } // Synapse: 111214;An attempt to complete a transaction has failed. No corresponding transaction found. - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsNotAzureSynapse))] - [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCommand), parameters: new object[] { 5 }, MemberType = typeof(RetryLogicTestHelper))] + [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsNotAzureSynapse), nameof(DataTestUtility.AreConnStringsSetup))] + [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCommand), parameters: new object[] { 5 }, MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] public void RetryExecuteWithTrans(string cnnString, SqlRetryLogicBaseProvider provider) { int numberOfTries = provider.RetryLogic.NumberOfTries; @@ -181,8 +181,8 @@ public void RetryExecuteWithTrans(string cnnString, SqlRetryLogicBaseProvider pr } // Synapse: Msg 103010, Level 16, State 1, Line 1 | Parse error at line: 1, column: 1: Incorrect syntax near 'command' - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsNotAzureSynapse))] - [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyFilterDMLStatements), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper))] + [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsNotAzureSynapse), nameof(DataTestUtility.AreConnStringsSetup))] + [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyFilterDMLStatements), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] public void RetryExecuteUnauthorizedSqlStatementDML(string cnnString, SqlRetryLogicBaseProvider provider) { int numberOfTries = provider.RetryLogic.NumberOfTries; @@ -235,8 +235,8 @@ public void RetryExecuteUnauthorizedSqlStatementDML(string cnnString, SqlRetryLo [ActiveIssue(14325)] // avoid creating a new database in Azure - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsNotAzureServer), nameof(DataTestUtility.IsNotAzureSynapse))] - [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyDropDB), parameters: new object[] { 5 }, MemberType = typeof(RetryLogicTestHelper))] + [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsNotAzureServer), nameof(DataTestUtility.IsNotAzureSynapse), nameof(DataTestUtility.AreConnStringsSetup))] + [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyDropDB), parameters: new object[] { 5 }, MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] public void DropDatabaseWithActiveConnection(string cnnString, SqlRetryLogicBaseProvider provider) { int currentRetries = 0; @@ -297,8 +297,8 @@ public void DropDatabaseWithActiveConnection(string cnnString, SqlRetryLogicBase // In Managed SNI by Named pipe connection, SqlCommand doesn't respect timeout. "ActiveIssue 12167" // Synapse: Does not support WAITFOR DELAY. - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsNotUsingManagedSNIOnWindows), nameof(DataTestUtility.IsNotAzureSynapse))] - [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyLockedTable), parameters: new object[] { 10 }, MemberType = typeof(RetryLogicTestHelper))] + [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsNotUsingManagedSNIOnWindows), nameof(DataTestUtility.IsNotAzureSynapse), nameof(DataTestUtility.AreConnStringsSetup))] + [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyLockedTable), parameters: new object[] { 10 }, MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] public void UpdateALockedTable(string cnnString, SqlRetryLogicBaseProvider provider) { int currentRetries = 0; @@ -355,7 +355,7 @@ public void UpdateALockedTable(string cnnString, SqlRetryLogicBaseProvider provi } [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - [MemberData(nameof(RetryLogicTestHelper.GetNoneRetriableCondition), MemberType = typeof(RetryLogicTestHelper))] + [MemberData(nameof(RetryLogicTestHelper.GetNoneRetriableCondition), MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] public void NoneRetriableExecuteFail(string cnnString, SqlRetryLogicBaseProvider provider) { string query = "SELECT bad command"; @@ -388,8 +388,8 @@ public void NoneRetriableExecuteFail(string cnnString, SqlRetryLogicBaseProvider #endregion #region Async - [Theory] - [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCommand), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper))] + [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] + [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCommand), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] public async void RetryExecuteAsyncFail(string cnnString, SqlRetryLogicBaseProvider provider) { int numberOfTries = provider.RetryLogic.NumberOfTries; @@ -453,8 +453,8 @@ public async void RetryExecuteAsyncFail(string cnnString, SqlRetryLogicBaseProvi } } - [Theory] - [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCommand), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper))] + [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] + [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCommand), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] public async void RetryExecuteAsyncCancel(string cnnString, SqlRetryLogicBaseProvider provider) { int numberOfTries = provider.RetryLogic.NumberOfTries; @@ -520,8 +520,8 @@ public async void RetryExecuteAsyncCancel(string cnnString, SqlRetryLogicBasePro #endregion #region Concurrent - [Theory] - [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCommand), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper))] + [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] + [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCommand), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] public void ConcurrentExecution(string cnnString, SqlRetryLogicBaseProvider provider) { int numberOfTries = provider.RetryLogic.NumberOfTries; diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConnectionReliabilityTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConnectionReliabilityTest.cs index 628866589e..624912f260 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConnectionReliabilityTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/RetryLogic/SqlConnectionReliabilityTest.cs @@ -12,12 +12,12 @@ namespace Microsoft.Data.SqlClient.ManualTesting.Tests public class SqlConnectionReliabilityTest { internal const string InvalidInitialCatalog = "InvalidInitialCatalog_for_retry"; - private readonly string _exceedErrMsgPattern = RetryLogicTestHelper.s_ExceedErrMsgPattern; - private readonly string _cancelErrMsgPattern = RetryLogicTestHelper.s_CancelErrMsgPattern; + private readonly string _exceedErrMsgPattern = RetryLogicTestHelper.s_exceedErrMsgPattern; + private readonly string _cancelErrMsgPattern = RetryLogicTestHelper.s_cancelErrMsgPattern; #region Sync - [Theory] - [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCatalog), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper))] + [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] + [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCatalog), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] public void ConnectionRetryOpenInvalidCatalogFailed(string cnnString, SqlRetryLogicBaseProvider provider) { int numberOfTries = provider.RetryLogic.NumberOfTries; @@ -33,8 +33,8 @@ public void ConnectionRetryOpenInvalidCatalogFailed(string cnnString, SqlRetryLo } } - [Theory] - [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCatalog), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper))] + [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] + [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCatalog), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] public void ConnectionCancelRetryOpenInvalidCatalog(string cnnString, SqlRetryLogicBaseProvider provider) { int cancelAfterRetries = provider.RetryLogic.NumberOfTries - 1; @@ -51,8 +51,8 @@ public void ConnectionCancelRetryOpenInvalidCatalog(string cnnString, SqlRetryLo [ActiveIssue(14590, TestPlatforms.Windows)] // avoid creating a new database in Azure - [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsNotAzureServer), nameof(DataTestUtility.IsNotAzureSynapse))] - [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyLongRunner), parameters: new object[] { 10 }, MemberType = typeof(RetryLogicTestHelper))] + [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsNotAzureServer), nameof(DataTestUtility.IsNotAzureSynapse), nameof(DataTestUtility.AreConnStringsSetup))] + [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyLongRunner), parameters: new object[] { 10 }, MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] public void CreateDatabaseWhileTryingToConnect(string cnnString, SqlRetryLogicBaseProvider provider) { int currentRetries = 0; @@ -98,8 +98,8 @@ public void CreateDatabaseWhileTryingToConnect(string cnnString, SqlRetryLogicBa Assert.True(currentRetries > 0); } - [Theory] - [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCatalog), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper))] + [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] + [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCatalog), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] public void ConcurrentExecution(string cnnString, SqlRetryLogicBaseProvider provider) { int numberOfTries = provider.RetryLogic.NumberOfTries; @@ -131,7 +131,7 @@ public void ConcurrentExecution(string cnnString, SqlRetryLogicBaseProvider prov } [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] - [MemberData(nameof(RetryLogicTestHelper.GetNoneRetriableCondition), MemberType = typeof(RetryLogicTestHelper))] + [MemberData(nameof(RetryLogicTestHelper.GetNoneRetriableCondition), MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] public void DefaultOpenWithoutRetry(string connectionString, SqlRetryLogicBaseProvider cnnProvider) { var cnnString = new SqlConnectionStringBuilder(connectionString) @@ -154,8 +154,8 @@ public void DefaultOpenWithoutRetry(string connectionString, SqlRetryLogicBasePr #endregion #region Async - [Theory] - [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCatalog), parameters: new object[] { 5 }, MemberType = typeof(RetryLogicTestHelper))] + [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] + [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCatalog), parameters: new object[] { 5 }, MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] public async void ConnectionRetryOpenAsyncInvalidCatalogFailed(string cnnString, SqlRetryLogicBaseProvider provider) { int numberOfTries = provider.RetryLogic.NumberOfTries; @@ -171,8 +171,8 @@ public async void ConnectionRetryOpenAsyncInvalidCatalogFailed(string cnnString, } } - [Theory] - [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCatalog), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper))] + [ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] + [MemberData(nameof(RetryLogicTestHelper.GetConnectionAndRetryStrategyInvalidCatalog), parameters: new object[] { 2 }, MemberType = typeof(RetryLogicTestHelper), DisableDiscoveryEnumeration = true)] public async void ConnectionCancelRetryOpenAsyncInvalidCatalog(string cnnString, SqlRetryLogicBaseProvider provider) { int numberOfTries = provider.RetryLogic.NumberOfTries;