From 110044ce277009254a270537b1394224625dc02a Mon Sep 17 00:00:00 2001 From: Erik Ejlskov Jensen Date: Mon, 24 Oct 2022 10:18:12 +0200 Subject: [PATCH 1/3] Add support for DateOnly and TimeOnly as SqlParameter value and with GetFieldValue(Async) --- .../SqlDataReader.xml | 32 +-- .../Microsoft/Data/SqlClient/SqlDataReader.cs | 10 + .../src/Microsoft/Data/SqlClient/SqlBuffer.cs | 37 ++- .../src/Microsoft/Data/SqlClient/SqlEnums.cs | 16 +- .../Microsoft/Data/SqlClient/SqlParameter.cs | 10 + .../tests/FunctionalTests/SqlParameterTest.cs | 110 ++++++++ .../ProviderAgnostic/ReaderTest/ReaderTest.cs | 111 +++++++- .../SQL/DateTimeTest/DateTimeTest.cs | 261 +++++++++++++++++- src/NuGet.config | 1 + 9 files changed, 567 insertions(+), 21 deletions(-) diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlDataReader.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlDataReader.xml index 8a789962d3..b0ce159fbf 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlDataReader.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlDataReader.xml @@ -327,14 +327,14 @@ ||||| |-|-|-|-| -|Boolean|Byte|Char|DateTime| -|DateTimeOffset|Decimal|Double|Float| -|Guid|Int16|Int32|Int64| -|SqlBoolean|SqlByte|SqlDateTime|SqlDecimal| -|SqlDouble|SqlGuid|SqlInt16|SqlInt32| -|SqlInt64|SqlMoney|SqlSingle|SqlString| -|Stream|String|TextReader|UDT, which can be any CLR type marked with .| -|XmlReader|||| +|Boolean|Byte|Char|DateOnly (.NET 6 or later)| +|DateTime|DateTimeOffset|Decimal|Double| +|Float|Guid|Int16|Int32| +|Int64|SqlBoolean|SqlByte|SqlDateTime| +|SqlDecimal|SqlDouble|SqlGuid|SqlInt16| +|SqlInt32|SqlInt64|SqlMoney|SqlSingle| +|SqlString|Stream|String|TextReader| +|TimeOnly (.NET 6 or later)|XmlReader||UDT, which can be any CLR type marked with .| For more information, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). @@ -369,14 +369,14 @@ ||||| |-|-|-|-| -|Boolean|Byte|Char|DateTime| -|DateTimeOffset|Decimal|Double|Float| -|Guid|Int16|Int32|Int64| -|SqlBoolean|SqlByte|SqlDateTime|SqlDecimal| -|SqlDouble|SqlGuid|SqlInt16|SqlInt32| -|SqlInt64|SqlMoney|SqlSingle|SqlString| -|Stream|String|TextReader|UDT, which can be any CLR type marked with .| -|XmlReader|||| +|Boolean|Byte|Char|DateOnly (.NET 6 or later)| +|DateTime|DateTimeOffset|Decimal|Double| +|Float|Guid|Int16|Int32| +|Int64|SqlBoolean|SqlByte|SqlDateTime| +|SqlDecimal|SqlDouble|SqlGuid|SqlInt16| +|SqlInt32|SqlInt64|SqlMoney|SqlSingle| +|SqlString|Stream|String|TextReader| +|TimeOnly (.NET 6 or later)|XmlReader||UDT, which can be any CLR type marked with .| For more information, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDataReader.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDataReader.cs index cf271ea749..3ea74785f0 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDataReader.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlDataReader.cs @@ -2843,6 +2843,16 @@ private T GetFieldValueFromSqlBufferInternal(SqlBuffer data, _SqlMetaData met { return (T)(object)data.DateTime; } +#if NET6_0_OR_GREATER + else if (typeof(T) == typeof(DateOnly) && dataType == typeof(DateTime) && _typeSystem > SqlConnectionString.TypeSystem.SQLServer2005 && metaData.Is2008DateTimeType) + { + return (T)(object)data.DateOnly; + } + else if (typeof(T) == typeof(TimeOnly) && dataType == typeof(TimeOnly) && _typeSystem > SqlConnectionString.TypeSystem.SQLServer2005 && metaData.Is2008DateTimeType) + { + return (T)(object)data.TimeOnly; + } +#endif else if (typeof(T) == typeof(XmlReader)) { // XmlReader only allowed on XML types diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlBuffer.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlBuffer.cs index 56ae335e46..686c5157ef 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlBuffer.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlBuffer.cs @@ -596,6 +596,37 @@ internal TimeSpan Time } } +#if NET6_0_OR_GREATER + internal TimeOnly TimeOnly + { + get + { + ThrowIfNull(); + + if (StorageType.Time == _type) + { + return new TimeOnly(_value._timeInfo._ticks); + } + + return (TimeOnly)Value; // anything else we haven't thought of goes through boxing. + } + } + + internal DateOnly DateOnly + { + get + { + ThrowIfNull(); + + if (StorageType.Date == _type) + { + return DateOnly.MinValue.AddDays(_value._int32); + } + return (DateOnly)Value; // anything else we haven't thought of goes through boxing. + } + } +#endif + internal DateTimeOffset DateTimeOffset { get @@ -1097,7 +1128,7 @@ internal Type GetTypeFromStorageType(bool isSqlType) return typeof(SqlGuid); case StorageType.SqlXml: return typeof(SqlXml); - // Date DateTime2 and DateTimeOffset have no direct Sql type to contain them + // Time Date DateTime2 and DateTimeOffset have no direct Sql type to contain them } } else @@ -1144,6 +1175,10 @@ internal Type GetTypeFromStorageType(bool isSqlType) return typeof(DateTime); case StorageType.DateTimeOffset: return typeof(DateTimeOffset); +#if NET6_0_OR_GREATER + case StorageType.Time: + return typeof(TimeOnly); +#endif } } diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlEnums.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlEnums.cs index bb474a0465..efd0083a9f 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlEnums.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlEnums.cs @@ -365,6 +365,16 @@ private static MetaType GetMetaTypeFromValue(Type dataType, object value, bool i { return MetaDateTimeOffset; } +#if NET6_0_OR_GREATER + else if (dataType == typeof(DateOnly)) + { + return s_metaDate; + } + else if (dataType == typeof(TimeOnly)) + { + return MetaTime; + } +#endif else { // UDT ? @@ -630,6 +640,10 @@ internal static object GetSqlValueFromComVariant(object comVal) break; case TimeSpan: case DateTimeOffset: +#if NET6_0_OR_GREATER + case TimeOnly: + case DateOnly: +#endif sqlVal = comVal; break; default: @@ -739,7 +753,7 @@ internal static SqlDbType GetSqlDbTypeFromOleDbType(short dbType, string typeNam break; // no direct mapping, just use SqlDbType.Variant; } return sqlType; -#else +#else // OleDbTypes not supported return SqlDbType.Variant; #endif // NETFRAMEWORK diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs index c78ef7dfc7..3eb0ce5ba2 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlParameter.cs @@ -2252,6 +2252,16 @@ internal static object CoerceValue(object value, MetaType destinationType, out b { value = new DateTimeOffset((DateTime)value); } +#if NET6_0_OR_GREATER + else if ((currentType == typeof(DateOnly)) && (destinationType.SqlDbType == SqlDbType.Date)) + { + value = ((DateOnly)value).ToDateTime(new TimeOnly(0, 0)); + } + else if ((currentType == typeof(TimeOnly)) && (destinationType.SqlDbType == SqlDbType.Time)) + { + value = ((TimeOnly)value).ToTimeSpan(); + } +#endif else if ( TdsEnums.SQLTABLE == destinationType.TDSType && ( diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlParameterTest.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlParameterTest.cs index 2f29b1bd15..40f82a2f1a 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlParameterTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlParameterTest.cs @@ -97,6 +97,64 @@ public void Constructor2_Value_DateTime() Assert.Equal(string.Empty, p.XmlSchemaCollectionOwningSchema); } +#if NET6_0_OR_GREATER + [Fact] + public void Constructor2_Value_DateOnly() + { + DateOnly value = new DateOnly(2004, 8, 24); + SqlParameter p = new SqlParameter("dateonly", value); + + Assert.Equal(DbType.Date, p.DbType); + Assert.Equal(ParameterDirection.Input, p.Direction); + Assert.False(p.IsNullable); + Assert.Equal(0, p.LocaleId); + Assert.Equal(0, p.Offset); + Assert.Equal("dateonly", p.ParameterName); + Assert.Equal(0, p.Precision); + Assert.Equal(0, p.Scale); + Assert.Equal(0, p.Size); + Assert.Equal(string.Empty, p.SourceColumn); + Assert.False(p.SourceColumnNullMapping); + Assert.Equal(DataRowVersion.Current, p.SourceVersion); + Assert.Equal(SqlDbType.Date, p.SqlDbType); + Assert.Equal(value, p.SqlValue); + Assert.Equal(string.Empty, p.TypeName); + Assert.Equal(string.Empty, p.UdtTypeName); + Assert.Equal(value, p.Value); + Assert.Equal(string.Empty, p.XmlSchemaCollectionDatabase); + Assert.Equal(string.Empty, p.XmlSchemaCollectionName); + Assert.Equal(string.Empty, p.XmlSchemaCollectionOwningSchema); + } + + [Fact] + public void Constructor2_Value_TimeOnly() + { + TimeOnly value = new TimeOnly(9, 7, 41, 321); + SqlParameter p = new SqlParameter("timeonly", value); + + Assert.Equal(DbType.Time, p.DbType); + Assert.Equal(ParameterDirection.Input, p.Direction); + Assert.False(p.IsNullable); + Assert.Equal(0, p.LocaleId); + Assert.Equal(0, p.Offset); + Assert.Equal("timeonly", p.ParameterName); + Assert.Equal(0, p.Precision); + Assert.Equal(0, p.Scale); + Assert.Equal(0, p.Size); + Assert.Equal(string.Empty, p.SourceColumn); + Assert.False(p.SourceColumnNullMapping); + Assert.Equal(DataRowVersion.Current, p.SourceVersion); + Assert.Equal(SqlDbType.Time, p.SqlDbType); + Assert.Equal(value, p.SqlValue); + Assert.Equal(string.Empty, p.TypeName); + Assert.Equal(string.Empty, p.UdtTypeName); + Assert.Equal(value, p.Value); + Assert.Equal(string.Empty, p.XmlSchemaCollectionDatabase); + Assert.Equal(string.Empty, p.XmlSchemaCollectionName); + Assert.Equal(string.Empty, p.XmlSchemaCollectionOwningSchema); + } +#endif + [Fact] public void Constructor2_Value_Null() { @@ -383,6 +441,58 @@ public void InferType_CharArray() Assert.Equal(value, p.Value); } +#if NET6_0_OR_GREATER + [Fact] + public void InferType_DateOnly() + { + DateOnly value; + SqlParameter param; + + value = DateOnly.FromDateTime(DateTime.Now.Date); + param = new SqlParameter(); + param.Value = value; + Assert.Equal(SqlDbType.Date, param.SqlDbType); + Assert.Equal(DbType.Date, param.DbType); + + value = DateOnly.FromDateTime(DateTime.Now.Date); + param = new SqlParameter(); + param.Value = value; + Assert.Equal(SqlDbType.Date, param.SqlDbType); + Assert.Equal(DbType.Date, param.DbType); + + value = DateOnly.FromDateTime(new DateTime(1973, 8, 13)); + param = new SqlParameter(); + param.Value = value; + Assert.Equal(SqlDbType.Date, param.SqlDbType); + Assert.Equal(DbType.Date, param.DbType); + } + + [Fact] + public void InferType_TimeOnly() + { + TimeOnly value; + SqlParameter param; + + value = TimeOnly.FromDateTime(DateTime.Now); + param = new SqlParameter(); + param.Value = value; + Assert.Equal(SqlDbType.Time, param.SqlDbType); + Assert.Equal(DbType.Time, param.DbType); + + value = TimeOnly.FromDateTime(DateTime.Now); + param = new SqlParameter(); + param.Value = value; + Assert.Equal(SqlDbType.Time, param.SqlDbType); + Assert.Equal(DbType.Time, param.DbType); + + value = TimeOnly.FromDateTime(new DateTime(2022, 10, 22, 15, 27, 38)); + param = new SqlParameter(); + param.Value = value; + Assert.Equal(SqlDbType.Time, param.SqlDbType); + Assert.Equal(DbType.Time, param.DbType); + } +#endif + [Fact] public void InferType_DateTime() { diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/ProviderAgnostic/ReaderTest/ReaderTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/ProviderAgnostic/ReaderTest/ReaderTest.cs index 697e57cb01..5d09be77f4 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/ProviderAgnostic/ReaderTest/ReaderTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/ProviderAgnostic/ReaderTest/ReaderTest.cs @@ -6,6 +6,7 @@ using System.Data.Common; using System.IO; using System.Text; +using System.Threading.Tasks; using Xunit; namespace Microsoft.Data.SqlClient.ManualTesting.Tests @@ -286,7 +287,7 @@ public static void SqlDataReader_SqlBuffer_GetFieldValue() con.ConnectionString = DataTestUtility.TCPConnectionString; con.Open(); string sqlQueryOne = $"CREATE TABLE {tableName} ([CustomerId] [int],[FirstName] [nvarchar](50),[BoolCol] [BIT],[ShortCol] [SMALLINT],[ByteCol] [TINYINT],[LongCol] [BIGINT]);"; - string sqlQueryTwo = $"ALTER TABLE {tableName} ADD [DoubleCol] [FLOAT],[SingleCol] [REAL],[GUIDCol] [uniqueidentifier],[DateTimeCol] [DateTime],[DecimalCol] [SmallMoney],[DateTimeOffsetCol] [DateTimeOffset];"; + string sqlQueryTwo = $"ALTER TABLE {tableName} ADD [DoubleCol] [FLOAT],[SingleCol] [REAL],[GUIDCol] [uniqueidentifier],[DateTimeCol] [DateTime],[DecimalCol] [SmallMoney],[DateTimeOffsetCol] [DateTimeOffset], [DateCol] [Date], [TimeCol] [Time];"; try { @@ -309,7 +310,7 @@ public static void SqlDataReader_SqlBuffer_GetFieldValue() { sqlCommand.CommandText = $"INSERT INTO {tableName} " + "VALUES (@CustomerId,@FirstName,@BoolCol,@ShortCol,@ByteCol,@LongCol,@DoubleCol,@SingleCol" - + ",@GUIDCol,@DateTimeCol,@DecimalCol,@DateTimeOffsetCol)"; + + ",@GUIDCol,@DateTimeCol,@DecimalCol,@DateTimeOffsetCol,@DateCol,@TimeCol)"; sqlCommand.Parameters.AddWithValue(@"CustomerId", 1); sqlCommand.Parameters.AddWithValue(@"FirstName", "Microsoft"); sqlCommand.Parameters.AddWithValue(@"BoolCol", true); @@ -322,6 +323,8 @@ public static void SqlDataReader_SqlBuffer_GetFieldValue() sqlCommand.Parameters.AddWithValue(@"DateTimeCol", dateTime); sqlCommand.Parameters.AddWithValue(@"DecimalCol", 280); sqlCommand.Parameters.AddWithValue(@"DateTimeOffsetCol", dtoffset); + sqlCommand.Parameters.AddWithValue(@"DateCol", new DateTime(2022, 10, 23)); + sqlCommand.Parameters.AddWithValue(@"TimeCol", new TimeSpan(0, 22, 7, 44)); sqlCommand.ExecuteNonQuery(); } using (SqlCommand sqlCommand = new SqlCommand("", con as SqlConnection)) @@ -343,6 +346,12 @@ public static void SqlDataReader_SqlBuffer_GetFieldValue() Assert.Equal(dateTime.ToString("dd/MM/yyyy HH:mm:ss.fff"), reader.GetFieldValue(9).ToString("dd/MM/yyyy HH:mm:ss.fff")); Assert.Equal(280, reader.GetFieldValue(10)); Assert.Equal(dtoffset, reader.GetFieldValue(11)); + Assert.Equal(new DateTime(2022, 10, 23), reader.GetFieldValue(12)); + Assert.Equal(new TimeSpan(0, 22, 7, 44), reader.GetFieldValue(13)); +#if NET6_0_OR_GREATER + Assert.Equal(new DateOnly(2022, 10, 23), reader.GetFieldValue(12)); + Assert.Equal(new TimeOnly(22, 7, 44), reader.GetFieldValue(13)); +#endif } } } @@ -357,5 +366,103 @@ public static void SqlDataReader_SqlBuffer_GetFieldValue() } } } + +#if NET6_0_OR_GREATER + /// + /// Covers GetFieldValue for SqlBuffer class + /// + [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] + public static async Task SqlDataReader_SqlBuffer_GetFieldValue_Async() + { + string tableName = DataTestUtility.GetUniqueNameForSqlServer("SqlBuffer_GetFieldValue_Async"); + DateTimeOffset dtoffset = DateTimeOffset.Now; + DateTime dt = DateTime.Now; + //Exclude the millisecond because of rounding at some points by SQL Server. + DateTime dateTime = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second); + //Arrange + DbProviderFactory provider = SqlClientFactory.Instance; + + using DbConnection con = provider.CreateConnection(); + con.ConnectionString = DataTestUtility.TCPConnectionString; + con.Open(); + string sqlQueryOne = $"CREATE TABLE {tableName} ([CustomerId] [int],[FirstName] [nvarchar](50),[BoolCol] [BIT],[ShortCol] [SMALLINT],[ByteCol] [TINYINT],[LongCol] [BIGINT]);"; + string sqlQueryTwo = $"ALTER TABLE {tableName} ADD [DoubleCol] [FLOAT],[SingleCol] [REAL],[GUIDCol] [uniqueidentifier],[DateTimeCol] [DateTime],[DecimalCol] [SmallMoney],[DateTimeOffsetCol] [DateTimeOffset], [DateCol] [Date], [TimeCol] [Time];"; + + try + { + using (DbCommand command = provider.CreateCommand()) + { + command.Connection = con; + command.CommandText = sqlQueryOne; + await command.ExecuteNonQueryAsync(); + } + using (DbCommand command = provider.CreateCommand()) + { + command.Connection = con; + command.CommandText = sqlQueryTwo; + await command.ExecuteNonQueryAsync(); + } + + System.Data.SqlTypes.SqlGuid sqlguid = new System.Data.SqlTypes.SqlGuid(Guid.NewGuid()); + + using (SqlCommand sqlCommand = new SqlCommand("", con as SqlConnection)) + { + sqlCommand.CommandText = $"INSERT INTO {tableName} " + + "VALUES (@CustomerId,@FirstName,@BoolCol,@ShortCol,@ByteCol,@LongCol,@DoubleCol,@SingleCol" + + ",@GUIDCol,@DateTimeCol,@DecimalCol,@DateTimeOffsetCol,@DateCol,@TimeCol)"; + sqlCommand.Parameters.AddWithValue(@"CustomerId", 1); + sqlCommand.Parameters.AddWithValue(@"FirstName", "Microsoft"); + sqlCommand.Parameters.AddWithValue(@"BoolCol", true); + sqlCommand.Parameters.AddWithValue(@"ShortCol", 3274); + sqlCommand.Parameters.AddWithValue(@"ByteCol", 253); + sqlCommand.Parameters.AddWithValue(@"LongCol", 922222222222); + sqlCommand.Parameters.AddWithValue(@"DoubleCol", 10.7); + sqlCommand.Parameters.AddWithValue(@"SingleCol", 123.546f); + sqlCommand.Parameters.AddWithValue(@"GUIDCol", sqlguid); + sqlCommand.Parameters.AddWithValue(@"DateTimeCol", dateTime); + sqlCommand.Parameters.AddWithValue(@"DecimalCol", 280); + sqlCommand.Parameters.AddWithValue(@"DateTimeOffsetCol", dtoffset); + sqlCommand.Parameters.AddWithValue(@"DateCol", new DateOnly(2022, 10, 23)); + sqlCommand.Parameters.AddWithValue(@"TimeCol", new TimeOnly(22, 7, 44)); + await sqlCommand.ExecuteNonQueryAsync(); + } + using (SqlCommand sqlCommand = new SqlCommand("", con as SqlConnection)) + { + sqlCommand.CommandText = "select top 1 * from " + tableName; + using (DbDataReader reader = await sqlCommand.ExecuteReaderAsync()) + { + Assert.True(reader.Read()); + Assert.Equal(1, await reader.GetFieldValueAsync(0)); + Assert.Equal("Microsoft", await reader.GetFieldValueAsync(1)); + Assert.True(await reader.GetFieldValueAsync(2)); + Assert.Equal(3274, await reader.GetFieldValueAsync(3)); + Assert.Equal(253, await reader.GetFieldValueAsync(4)); + Assert.Equal(922222222222, await reader.GetFieldValueAsync(5)); + Assert.Equal(10.7, await reader.GetFieldValueAsync(6)); + Assert.Equal(123.546f, await reader.GetFieldValueAsync(7)); + Assert.Equal(sqlguid, await reader.GetFieldValueAsync(8)); + Assert.Equal(sqlguid.Value, (await reader.GetFieldValueAsync(8)).Value); + Assert.Equal(dateTime.ToString("dd/MM/yyyy HH:mm:ss.fff"), (await reader.GetFieldValueAsync(9)).ToString("dd/MM/yyyy HH:mm:ss.fff")); + Assert.Equal(280, await reader.GetFieldValueAsync(10)); + Assert.Equal(dtoffset, await reader.GetFieldValueAsync(11)); + Assert.Equal(new DateTime(2022, 10, 23), await reader.GetFieldValueAsync(12)); + Assert.Equal(new TimeSpan(0, 22, 7, 44), await reader.GetFieldValueAsync(13)); + Assert.Equal(new DateOnly(2022, 10, 23), await reader.GetFieldValueAsync(12)); + Assert.Equal(new TimeOnly(22, 7, 44), await reader.GetFieldValueAsync(13)); + } + } + } + finally + { + //cleanup + using (DbCommand cmd = provider.CreateCommand()) + { + cmd.Connection = con; + cmd.CommandText = "drop table " + tableName; + await cmd.ExecuteNonQueryAsync(); + } + } + } +#endif } } diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DateTimeTest/DateTimeTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DateTimeTest/DateTimeTest.cs index f89017c811..f5e58ab015 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DateTimeTest/DateTimeTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/DateTimeTest/DateTimeTest.cs @@ -188,7 +188,7 @@ public static void ReaderParameterTest() Assert.True(p0.Value.Equals((new SqlDateTime(1753, 1, 1, 0, 0, 0)).Value), "FAILED: SqlParameter p0 contained incorrect value"); Assert.True(p1.Value.Equals(new DateTime(1753, 1, 1, 0, 0, 0)), "FAILED: SqlParameter p1 contained incorrect value"); Assert.True(p2.Value.Equals(new TimeSpan(0, 20, 12, 13, 360)), "FAILED: SqlParameter p2 contained incorrect value"); - Assert.True(p2.Scale.Equals(7), "FAILED: SqlParameter p0 contained incorrect scale"); + Assert.True(p2.Scale.Equals(7), "FAILED: SqlParameter p2 contained incorrect scale"); Assert.True(p3.Value.Equals(new DateTime(2000, 12, 31, 23, 59, 59, 997)), "FAILED: SqlParameter p3 contained incorrect value"); Assert.True(p3.Scale.Equals(7), "FAILED: SqlParameter p3 contained incorrect scale"); Assert.True(p4.Value.Equals(new DateTimeOffset(9999, 12, 31, 23, 59, 59, 997, TimeSpan.Zero)), "FAILED: SqlParameter p4 contained incorrect value"); @@ -212,6 +212,10 @@ public static void ReaderParameterTest() Assert.True(IsValidParam(SqlDbType.Date, "c1", new DateTime(1753, 1, 1, 0, 0, 0, DateTimeKind.Local), conn, tableName), "FAILED: Invalid param for Date SqlDbType"); Assert.False(IsValidParam(SqlDbType.Date, "c1", new TimeSpan(), conn, tableName), "FAILED: Invalid param for Date SqlDbType"); Assert.True(IsValidParam(SqlDbType.Date, "c1", "1753-1-1", conn, tableName), "FAILED: Invalid param for Date SqlDbType"); +#if NET6_0_OR_GREATER + Assert.True(IsValidParam(SqlDbType.Date, "c1", new DateOnly(1753, 1, 1), conn, tableName), "FAILED: Invalid param for Date SqlDbType"); + Assert.False(IsValidParam(SqlDbType.Date, "c1", new TimeOnly(), conn, tableName), "FAILED: Invalid param for Date SqlDbType"); +#endif // Time Assert.False(IsValidParam(SqlDbType.Time, "c2", new DateTimeOffset(1753, 1, 1, 0, 0, 0, TimeSpan.Zero), conn, tableName), "FAILED: Invalid param for Time SqlDbType"); @@ -221,6 +225,10 @@ public static void ReaderParameterTest() Assert.False(IsValidParam(SqlDbType.Time, "c2", new DateTime(1753, 1, 1, 0, 0, 0, DateTimeKind.Local), conn, tableName), "FAILED: Invalid param for Time SqlDbType"); Assert.True(IsValidParam(SqlDbType.Time, "c2", TimeSpan.Parse("20:12:13.36"), conn, tableName), "FAILED: Invalid param for Time SqlDbType"); Assert.True(IsValidParam(SqlDbType.Time, "c2", "20:12:13.36", conn, tableName), "FAILED: Invalid param for Time SqlDbType"); +#if NET6_0_OR_GREATER + Assert.False(IsValidParam(SqlDbType.Time, "c2", new DateOnly(1753, 1, 1), conn, tableName), "FAILED: Invalid param for Time SqlDbType"); + Assert.True(IsValidParam(SqlDbType.Time, "c2", new TimeOnly(20, 12, 13, 360), conn, tableName), "FAILED: Invalid param for Time SqlDbType"); +#endif // DateTime2 DateTime dt = DateTime.Parse("2000-12-31 23:59:59.997"); @@ -374,6 +382,10 @@ public static void ReaderParameterTest() Assert.True(IsValidParam(DbType.Date, "c1", new DateTime(1753, 1, 1, 0, 0, 0, DateTimeKind.Local), conn, tableName), "FAILED: Invalid param for Date DbType"); Assert.False(IsValidParam(DbType.Date, "c1", new TimeSpan(), conn, tableName), "FAILED: Invalid param for Date DbType"); Assert.True(IsValidParam(DbType.Date, "c1", "1753-1-1", conn, tableName), "FAILED: Invalid param for Date DbType"); +#if NET6_0_OR_GREATER + Assert.True(IsValidParam(DbType.Date, "c1", new DateOnly(1753, 1, 1), conn, tableName), "FAILED: Invalid param for Date DbType"); + Assert.False(IsValidParam(DbType.Date, "c1", new TimeOnly(), conn, tableName), "FAILED: Invalid param for Date DbType"); +#endif // Time // These 7 Asserts used to be broken for before removing back-compat code for DbType.Date and DbType.Time parameters @@ -384,6 +396,10 @@ public static void ReaderParameterTest() Assert.False(IsValidParam(DbType.Time, "c2", new DateTime(1753, 1, 1, 0, 0, 0, DateTimeKind.Local), conn, tableName), "FAILED: Invalid param for Time DbType"); Assert.True(IsValidParam(DbType.Time, "c2", TimeSpan.Parse("20:12:13.36"), conn, tableName), "FAILED: Invalid param for Time DbType"); Assert.True(IsValidParam(DbType.Time, "c2", "20:12:13.36", conn, tableName), "FAILED: Invalid param for Time DbType"); +#if NET6_0_OR_GREATER + Assert.False(IsValidParam(DbType.Time, "c2", new DateOnly(1753, 1, 1), conn, tableName), "FAILED: Invalid param for Time DbType"); + Assert.True(IsValidParam(DbType.Time, "c2", new TimeOnly(20, 12, 13, 360), conn, tableName), "FAILED: Invalid param for Time DbType"); +#endif // DateTime2 DateTime dt = DateTime.Parse("2000-12-31 23:59:59.997"); @@ -504,6 +520,249 @@ public static void ReaderParameterTest() } } +#if NET6_0_OR_GREATER + // Synapse: CREATE or ALTER PROCEDURE statement uses syntax or features that are not supported in SQL Server PDW. + [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] + public static void ReaderParameterTest_DateOnly_TimeOnly() + { + string tableName = "#t_" + Guid.NewGuid().ToString().Replace('-', '_'); + string procName = "#p_" + Guid.NewGuid().ToString().Replace('-', '_'); + string procNullName = "#pn_" + Guid.NewGuid().ToString().Replace('-', '_'); + + string tempTableCreate = "CREATE TABLE " + tableName + " (ci int, c1 date, c2 time(7) )"; + string tempTableInsert1 = "INSERT INTO " + tableName + " VALUES (0, " + + "'1753-01-01', " + + "'20:12:13.36')"; + string tempTableInsert2 = "INSERT INTO " + tableName + " VALUES (@pi, @p1, @p2)"; + + string createProc = "CREATE PROCEDURE " + procName + " @p1 date OUTPUT, @p2 time(7) OUTPUT"; + createProc += " AS "; + createProc += " SET @p1 = '1753-01-01'"; + createProc += " SET @p2 = '20:12:13.36'"; + + string createProcN = "CREATE PROCEDURE " + procNullName + " @p1 date OUTPUT, @p2 time(7) OUTPUT"; + createProcN += " AS "; + createProcN += " SET @p1 = NULL"; + createProcN += " SET @p2 = NULL"; + + using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString)) + { + try + { + // ReaderParameterTest Setup + conn.Open(); + using (SqlCommand cmd = conn.CreateCommand()) + { + cmd.CommandText = tempTableCreate; + cmd.ExecuteNonQuery(); + cmd.CommandText = tempTableInsert1; + cmd.ExecuteNonQuery(); + + #region parameter + // Parameter Tests + // Test 1 + using (SqlCommand cmd2 = conn.CreateCommand()) + { + cmd2.CommandText = tempTableInsert2; + SqlParameter pi = cmd2.Parameters.Add("@pi", SqlDbType.Int); + SqlParameter p1 = cmd2.Parameters.Add("@p1", SqlDbType.Date); + SqlParameter p2 = cmd2.Parameters.Add("@p2", SqlDbType.Time); + pi.Value = DBNull.Value; + p1.Value = DBNull.Value; + p2.Value = DBNull.Value; + + cmd2.ExecuteNonQuery(); + pi.Value = 1; + p1.Value = new DateOnly(2000, 12, 31); + p2.Value = new TimeOnly(23, 59, 59); + cmd2.ExecuteNonQuery(); + + // Test 2 + cmd2.CommandText = "SELECT COUNT(*) FROM " + tableName + " WHERE @pi = ci AND @p1 = c1 AND @p2 = c2"; + pi.Value = 0; + p1.Value = new DateOnly(1753, 1, 1); + p2.Value = new TimeOnly(20, 12, 13, 360); + object scalarResult = cmd2.ExecuteScalar(); + Assert.True(scalarResult.Equals(1), string.Format("FAILED: Execute scalar returned unexpected result. Expected: {0}. Actual: {1}.", 1, scalarResult)); + + cmd2.Parameters.Clear(); + pi = cmd2.Parameters.Add("@pi", SqlDbType.Int); + p1 = cmd2.Parameters.Add("@p1", SqlDbType.Date); + p2 = cmd2.Parameters.Add("@p2", SqlDbType.Time); + pi.SqlValue = new SqlInt32(0); + p1.SqlValue = new DateOnly(1753, 1, 1); + p2.SqlValue = new TimeOnly(20, 12, 13, 360); + p2.Scale = 3; + scalarResult = cmd2.ExecuteScalar(); + Assert.True(scalarResult.Equals(1), string.Format("FAILED: ExecutScalar returned unexpected result. Expected: {0}. Actual: {1}.", 1, scalarResult)); + + // Test 3 + + cmd.CommandText = createProc; + cmd.ExecuteNonQuery(); + cmd.CommandText = createProcN; + cmd.ExecuteNonQuery(); + using (SqlCommand cmd3 = conn.CreateCommand()) + { + cmd3.CommandType = CommandType.StoredProcedure; + cmd3.CommandText = procName; + p1 = cmd3.Parameters.Add("@p1", SqlDbType.Date); + p2 = cmd3.Parameters.Add("@p2", SqlDbType.Time); + p1.Direction = ParameterDirection.Output; + p2.Direction = ParameterDirection.Output; + p2.Scale = 7; + cmd3.ExecuteNonQuery(); + + Assert.True(p1.Value.Equals(new DateTime(1753, 1, 1)), "FAILED: SqlParameter p1 contained incorrect value"); + Assert.True(p2.Value.Equals(new TimeSpan(0, 20, 12, 13, 360)), "FAILED: SqlParameter p2 contained incorrect value"); + Assert.True(p2.Scale.Equals(7), "FAILED: SqlParameter p0 contained incorrect scale"); + + // Test 4 + cmd3.CommandText = procNullName; + cmd3.ExecuteNonQuery(); + } + Assert.True(p1.Value.Equals(DBNull.Value), "FAILED: SqlParameter p1 expected to be NULL"); + Assert.True(p2.Value.Equals(DBNull.Value), "FAILED: SqlParameter p2 expected to be NULL"); + + // Date + Assert.False(IsValidParam(SqlDbType.Date, "c1", new DateTimeOffset(1753, 1, 1, 0, 0, 0, TimeSpan.Zero), conn, tableName), "FAILED: Invalid param for Date SqlDbType"); + Assert.False(IsValidParam(SqlDbType.Date, "c1", new SqlDateTime(1753, 1, 1, 0, 0, 0), conn, tableName), "FAILED: Invalid param for Date SqlDbType"); + Assert.True(IsValidParam(SqlDbType.Date, "c1", new DateTime(1753, 1, 1, 0, 0, 0, DateTimeKind.Unspecified), conn, tableName), "FAILED: Invalid param for Date SqlDbType"); + Assert.True(IsValidParam(SqlDbType.Date, "c1", new DateTime(1753, 1, 1, 0, 0, 0, DateTimeKind.Utc), conn, tableName), "FAILED: Invalid param for Date SqlDbType"); + Assert.True(IsValidParam(SqlDbType.Date, "c1", new DateTime(1753, 1, 1, 0, 0, 0, DateTimeKind.Local), conn, tableName), "FAILED: Invalid param for Date SqlDbType"); + Assert.False(IsValidParam(SqlDbType.Date, "c1", new TimeSpan(), conn, tableName), "FAILED: Invalid param for Date SqlDbType"); + Assert.True(IsValidParam(SqlDbType.Date, "c1", "1753-1-1", conn, tableName), "FAILED: Invalid param for Date SqlDbType"); + Assert.True(IsValidParam(SqlDbType.Date, "c1", new DateOnly(1753, 1, 1), conn, tableName), "FAILED: Invalid param for Date SqlDbType"); + Assert.False(IsValidParam(SqlDbType.Date, "c1", new TimeOnly(), conn, tableName), "FAILED: Invalid param for Date SqlDbType"); + + // Time + Assert.False(IsValidParam(SqlDbType.Time, "c2", new DateTimeOffset(1753, 1, 1, 0, 0, 0, TimeSpan.Zero), conn, tableName), "FAILED: Invalid param for Time SqlDbType"); + Assert.False(IsValidParam(SqlDbType.Time, "c2", new SqlDateTime(1753, 1, 1, 0, 0, 0), conn, tableName), "FAILED: Invalid param for Time SqlDbType"); + Assert.False(IsValidParam(SqlDbType.Time, "c2", new DateTime(1753, 1, 1, 0, 0, 0, DateTimeKind.Unspecified), conn, tableName), "FAILED: Invalid param for Time SqlDbType"); + Assert.False(IsValidParam(SqlDbType.Time, "c2", new DateTime(1753, 1, 1, 0, 0, 0, DateTimeKind.Utc), conn, tableName), "FAILED: Invalid param for Time SqlDbType"); + Assert.False(IsValidParam(SqlDbType.Time, "c2", new DateTime(1753, 1, 1, 0, 0, 0, DateTimeKind.Local), conn, tableName), "FAILED: Invalid param for Time SqlDbType"); + Assert.True(IsValidParam(SqlDbType.Time, "c2", TimeSpan.Parse("20:12:13.36"), conn, tableName), "FAILED: Invalid param for Time SqlDbType"); + Assert.True(IsValidParam(SqlDbType.Time, "c2", "20:12:13.36", conn, tableName), "FAILED: Invalid param for Time SqlDbType"); + Assert.False(IsValidParam(SqlDbType.Time, "c2", new DateOnly(1753, 1, 1), conn, tableName), "FAILED: Invalid param for Time SqlDbType"); + Assert.True(IsValidParam(SqlDbType.Time, "c2", new TimeOnly(20, 12, 13, 360), conn, tableName), "FAILED: Invalid param for Time SqlDbType"); + } + + // Do the same thing as above except using DbType now + using (DbCommand cmd3 = conn.CreateCommand()) + { + cmd3.CommandText = tempTableInsert2; + DbParameter pi = cmd3.CreateParameter(); + pi.DbType = DbType.Int32; + pi.ParameterName = "@pi"; + DbParameter p1 = cmd3.CreateParameter(); + p1.DbType = DbType.Date; + p1.ParameterName = "@p1"; + DbParameter p2 = cmd3.CreateParameter(); + p2.DbType = DbType.Time; + p2.ParameterName = "@p2"; + pi.Value = DBNull.Value; + p1.Value = DBNull.Value; + p2.Value = DBNull.Value; + + cmd3.Parameters.Add(pi); + cmd3.Parameters.Add(p1); + cmd3.Parameters.Add(p2); + cmd3.ExecuteNonQuery(); + pi.Value = 1; + p1.Value = new DateOnly(2000, 12, 31); + p2.Value = new TimeOnly(23, 59, 59); + + // This used to be broken for p2/TimeSpan before removing back-compat code for DbType.Date and DbType.Time parameters + cmd3.ExecuteNonQuery(); + + // Test 2 + cmd3.CommandText = "SELECT COUNT(*) FROM " + tableName + " WHERE @pi = ci AND @p1 = c1 AND @p2 = c2"; + pi.Value = 0; + p1.Value = new DateOnly(1753, 1, 1); + p2.Value = new TimeOnly(20, 12, 13, 360); + cmd3.Parameters.Clear(); + cmd3.Parameters.Add(pi); + cmd3.Parameters.Add(p1); + cmd3.Parameters.Add(p2); + + // This used to be broken for p2/TimeSpan before removing back-compat code for DbType.Date and DbType.Time parameters + object scalarResult = cmd3.ExecuteScalar(); + Assert.True(scalarResult.Equals(1), string.Format("FAILED: Execute scalar returned unexpected result. Expected: {0}. Actual: {1}.", 1, scalarResult)); + + // Test 3 + + using (SqlCommand cmd4 = conn.CreateCommand()) + { + cmd4.CommandType = CommandType.StoredProcedure; + cmd4.CommandText = procName; + p1 = cmd3.CreateParameter(); + p1.DbType = DbType.Date; + p1.ParameterName = "@p1"; + cmd4.Parameters.Add(p1); + p2 = cmd3.CreateParameter(); + p2.DbType = DbType.Time; + p2.ParameterName = "@p2"; + cmd4.Parameters.Add(p2); + p1.Direction = ParameterDirection.Output; + p2.Direction = ParameterDirection.Output; + p2.Scale = 7; + cmd4.ExecuteNonQuery(); + + Assert.True(p1.Value.Equals(new DateTime(1753, 1, 1, 0, 0, 0)), "FAILED: SqlParameter p1 contained incorrect value"); + // This used to be broken for p2/TimeSpan before removing back-compat code for DbType.Date and DbType.Time parameters + Assert.True(p2.Value.Equals(new TimeSpan(0, 20, 12, 13, 360)), "FAILED: SqlParameter p2 contained incorrect value"); + Assert.True(p2.Scale.Equals(7), "FAILED: SqlParameter p0 contained incorrect scale"); + + // Test 4 + cmd4.CommandText = procNullName; + cmd4.ExecuteNonQuery(); + } + Assert.True(p1.Value.Equals(DBNull.Value), "FAILED: SqlParameter p1 expected to be NULL"); + Assert.True(p2.Value.Equals(DBNull.Value), "FAILED: SqlParameter p2 expected to be NULL"); + + // Date + Assert.False(IsValidParam(DbType.Date, "c1", new DateTimeOffset(1753, 1, 1, 0, 0, 0, TimeSpan.Zero), conn, tableName), "FAILED: Invalid param for Date DbType"); + Assert.False(IsValidParam(DbType.Date, "c1", new SqlDateTime(1753, 1, 1, 0, 0, 0), conn, tableName), "FAILED: Invalid param for Date DbType"); + Assert.True(IsValidParam(DbType.Date, "c1", new DateTime(1753, 1, 1, 0, 0, 0, DateTimeKind.Unspecified), conn, tableName), "FAILED: Invalid param for Date DbType"); + Assert.True(IsValidParam(DbType.Date, "c1", new DateTime(1753, 1, 1, 0, 0, 0, DateTimeKind.Utc), conn, tableName), "FAILED: Invalid param for Date DbType"); + Assert.True(IsValidParam(DbType.Date, "c1", new DateTime(1753, 1, 1, 0, 0, 0, DateTimeKind.Local), conn, tableName), "FAILED: Invalid param for Date DbType"); + Assert.False(IsValidParam(DbType.Date, "c1", new TimeSpan(), conn, tableName), "FAILED: Invalid param for Date DbType"); + Assert.True(IsValidParam(DbType.Date, "c1", "1753-1-1", conn, tableName), "FAILED: Invalid param for Date DbType"); + Assert.True(IsValidParam(DbType.Date, "c1", new DateOnly(1753, 1, 1), conn, tableName), "FAILED: Invalid param for Date DbType"); + Assert.False(IsValidParam(DbType.Date, "c1", new TimeOnly(), conn, tableName), "FAILED: Invalid param for Date DbType"); + + // Time + // These 7 Asserts used to be broken for before removing back-compat code for DbType.Date and DbType.Time parameters + Assert.False(IsValidParam(DbType.Time, "c2", new DateTimeOffset(1753, 1, 1, 0, 0, 0, TimeSpan.Zero), conn, tableName), "FAILED: Invalid param for Time DbType"); + Assert.False(IsValidParam(DbType.Time, "c2", new SqlDateTime(1753, 1, 1, 0, 0, 0), conn, tableName), "FAILED: Invalid param for Time DbType"); + Assert.False(IsValidParam(DbType.Time, "c2", new DateTime(1753, 1, 1, 0, 0, 0, DateTimeKind.Unspecified), conn, tableName), "FAILED: Invalid param for Time DbType"); + Assert.False(IsValidParam(DbType.Time, "c2", new DateTime(1753, 1, 1, 0, 0, 0, DateTimeKind.Utc), conn, tableName), "FAILED: Invalid param for Time DbType"); + Assert.False(IsValidParam(DbType.Time, "c2", new DateTime(1753, 1, 1, 0, 0, 0, DateTimeKind.Local), conn, tableName), "FAILED: Invalid param for Time DbType"); + Assert.True(IsValidParam(DbType.Time, "c2", TimeSpan.Parse("20:12:13.36"), conn, tableName), "FAILED: Invalid param for Time DbType"); + Assert.True(IsValidParam(DbType.Time, "c2", "20:12:13.36", conn, tableName), "FAILED: Invalid param for Time DbType"); + Assert.False(IsValidParam(DbType.Time, "c2", new DateOnly(1753, 1, 1), conn, tableName), "FAILED: Invalid param for Time DbType"); + Assert.True(IsValidParam(DbType.Time, "c2", new TimeOnly(20, 12, 13, 360), conn, tableName), "FAILED: Invalid param for Time DbType"); + } + #endregion + + } + } + finally + { + using (SqlCommand cmd = conn.CreateCommand()) + { + cmd.CommandText = "DROP TABLE " + tableName; + cmd.ExecuteNonQuery(); + cmd.CommandText = "DROP PROCEDURE " + procName; + cmd.ExecuteNonQuery(); + cmd.CommandText = "DROP PROCEDURE " + procNullName; + cmd.ExecuteNonQuery(); + } + } + } + } +#endif + [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] public static void TypeVersionKnobTest() { diff --git a/src/NuGet.config b/src/NuGet.config index 5832a9da27..366141ab39 100644 --- a/src/NuGet.config +++ b/src/NuGet.config @@ -3,5 +3,6 @@ + From b46ac2fd18e3423bb3649de9dfffcb88f8abf909 Mon Sep 17 00:00:00 2001 From: Erik Ejlskov Jensen Date: Tue, 25 Oct 2022 07:36:55 +0200 Subject: [PATCH 2/3] Kick CI --- .../tests/FunctionalTests/SqlParameterTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlParameterTest.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlParameterTest.cs index 40f82a2f1a..7a6abdded6 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlParameterTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlParameterTest.cs @@ -129,7 +129,7 @@ public void Constructor2_Value_DateOnly() [Fact] public void Constructor2_Value_TimeOnly() { - TimeOnly value = new TimeOnly(9, 7, 41, 321); + TimeOnly value = new TimeOnly(9, 7, 42, 321); SqlParameter p = new SqlParameter("timeonly", value); Assert.Equal(DbType.Time, p.DbType); From a515e66d16ffcf96c1e845ae266a98884171f64c Mon Sep 17 00:00:00 2001 From: Erik Ejlskov Jensen Date: Wed, 2 Nov 2022 07:30:32 +0100 Subject: [PATCH 3/3] Remove added package source --- src/NuGet.config | 1 - 1 file changed, 1 deletion(-) diff --git a/src/NuGet.config b/src/NuGet.config index 366141ab39..5832a9da27 100644 --- a/src/NuGet.config +++ b/src/NuGet.config @@ -3,6 +3,5 @@ -