From 6236fe98b8777d80573d64c885e51c817b0111c0 Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Mon, 23 Dec 2019 16:49:59 -0800 Subject: [PATCH 1/3] Fix issues with SqlCommandSet not copying Byte Array parameters correctly --- .../Microsoft/Data/SqlClient/SqlCommandSet.cs | 2 +- .../Microsoft/Data/SqlClient/SqlCommandSet.cs | 2 +- ....Data.SqlClient.ManualTesting.Tests.csproj | 1 + .../SQL/SqlCommand/SqlCommandSetTest.cs | 92 +++++++++++++++++++ 4 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandSetTest.cs diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommandSet.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommandSet.cs index 361461f354..65e92f0098 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommandSet.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommandSet.cs @@ -153,7 +153,7 @@ internal void Append(SqlCommand command) if (null != byteValues) { int offset = p.Offset; - int size = p.Size; + int size = p.GetActualSize(); int countOfBytes = byteValues.Length - offset; if ((0 != size) && (size < countOfBytes)) { diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommandSet.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommandSet.cs index 4be0ed8d5d..48847cd96b 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommandSet.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommandSet.cs @@ -180,7 +180,7 @@ internal void Append(SqlCommand command) if (null != byteValues) { int offset = p.Offset; - int size = p.Size; + int size = p.GetActualSize; int countOfBytes = byteValues.Length - offset; if ((0 != size) && (size < countOfBytes)) { diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj b/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj index cf3600d671..d88504b197 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj @@ -113,6 +113,7 @@ + diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandSetTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandSetTest.cs new file mode 100644 index 0000000000..57b09f08bd --- /dev/null +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandSetTest.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using System.Data.SqlTypes; +using System.Reflection; +using System.Text; +using Xunit; + +namespace Microsoft.Data.SqlClient.ManualTesting.Tests +{ + public class SqlCommandSetTest + { + private static Assembly mds = Assembly.GetAssembly(typeof(SqlConnection)); + + [CheckConnStrSetupFact] + public void TestByteArrayParameters() + { + string tableName = DataTestUtility.GetUniqueName("CMD"); + string procName = DataTestUtility.GetUniqueName("CMD"); + byte[] bArray = new byte[] { 1, 2, 3 }; + + using (var connection = new SqlConnection(DataTestUtility.TCPConnectionString)) + using (var cmd = new SqlCommand(procName, connection)) + { + try + { + connection.Open(); + + setupByteArrayArtifacts(connection, tableName, procName); + + // Insert with SqlCommand + cmd.CommandType = System.Data.CommandType.StoredProcedure; + SqlCommandBuilder.DeriveParameters(cmd); + cmd.Parameters["@array"].Value = bArray; + + cmd.ExecuteNonQuery(); + + //Insert with command Set + var commandSetType = mds.GetType("Microsoft.Data.SqlClient.SqlCommandSet"); + var cmdSet = Activator.CreateInstance(commandSetType, true); + commandSetType.GetMethod("Append", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).Invoke(cmdSet, new object[] { cmd }); + commandSetType.GetProperty("Connection", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetSetMethod(true).Invoke(cmdSet, new object[] { connection }); + commandSetType.GetMethod("ExecuteNonQuery", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).Invoke(cmdSet, new object[] { }); + + cmd.CommandType = System.Data.CommandType.Text; + cmd.CommandText = $"SELECT * FROM {tableName}"; + using (SqlDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + SqlBytes byteArray = reader.GetSqlBytes(0); + Assert.Equal(byteArray.Length, bArray.Length); + + for (int i = 0; i < bArray.Length; i++) + { + Assert.Equal(bArray[i], byteArray[i]); + } + } + } + } + finally + { + dropByteArrayArtifacts(connection, tableName, procName); + } + } + } + + private void dropByteArrayArtifacts(SqlConnection connection, string tableName, string procName) + { + using (SqlCommand cmd = connection.CreateCommand()) + { + cmd.CommandText = $"DROP TABLE IF EXISTS {tableName}"; + cmd.ExecuteNonQuery(); + + cmd.CommandText = $"DROP PROCEDURE IF EXISTS {procName}"; + cmd.ExecuteNonQuery(); + } + } + + private void setupByteArrayArtifacts(SqlConnection connection, string tableName, string procName) + { + using (SqlCommand cmd = connection.CreateCommand()) + { + cmd.CommandText = $"CREATE TABLE {tableName} (ByteArrayColumn varbinary(max))"; + cmd.ExecuteNonQuery(); + + cmd.CommandText = $"CREATE PROCEDURE {procName} @array varbinary(max) AS BEGIN SET NOCOUNT ON; " + + $"insert into {tableName}(ByteArrayColumn) values(@array) END"; + cmd.ExecuteNonQuery(); + } + } + } +} From 7a61da66f463a71236b28abb201b8de49d8a790b Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Mon, 23 Dec 2019 17:07:03 -0800 Subject: [PATCH 2/3] Minor --- .../netfx/src/Microsoft/Data/SqlClient/SqlCommandSet.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommandSet.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommandSet.cs index 48847cd96b..733e5861ea 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommandSet.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommandSet.cs @@ -180,7 +180,7 @@ internal void Append(SqlCommand command) if (null != byteValues) { int offset = p.Offset; - int size = p.GetActualSize; + int size = p.GetActualSize(); int countOfBytes = byteValues.Length - offset; if ((0 != size) && (size < countOfBytes)) { From 84ad70d8cfff36c3792c9561870d4e04492d3deb Mon Sep 17 00:00:00 2001 From: Cheena Malhotra Date: Mon, 23 Dec 2019 17:32:05 -0800 Subject: [PATCH 3/3] Edits --- .../netcore/src/Microsoft/Data/SqlClient/SqlCommandSet.cs | 4 ++-- .../netfx/src/Microsoft/Data/SqlClient/SqlCommandSet.cs | 4 ++-- .../tests/ManualTests/SQL/SqlCommand/SqlCommandSetTest.cs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommandSet.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommandSet.cs index 65e92f0098..4d51c01f86 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommandSet.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommandSet.cs @@ -153,9 +153,9 @@ internal void Append(SqlCommand command) if (null != byteValues) { int offset = p.Offset; - int size = p.GetActualSize(); + int size = p.Size; int countOfBytes = byteValues.Length - offset; - if ((0 != size) && (size < countOfBytes)) + if ((size > 0) && (size < countOfBytes)) { countOfBytes = size; } diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommandSet.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommandSet.cs index 733e5861ea..d47f33ed67 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommandSet.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommandSet.cs @@ -180,9 +180,9 @@ internal void Append(SqlCommand command) if (null != byteValues) { int offset = p.Offset; - int size = p.GetActualSize(); + int size = p.Size; int countOfBytes = byteValues.Length - offset; - if ((0 != size) && (size < countOfBytes)) + if ((size > 0) && (size < countOfBytes)) { countOfBytes = size; } diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandSetTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandSetTest.cs index 57b09f08bd..6d6484de3d 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandSetTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/SqlCommand/SqlCommandSetTest.cs @@ -14,8 +14,8 @@ public class SqlCommandSetTest [CheckConnStrSetupFact] public void TestByteArrayParameters() { - string tableName = DataTestUtility.GetUniqueName("CMD"); - string procName = DataTestUtility.GetUniqueName("CMD"); + string tableName = DataTestUtility.GetUniqueNameForSqlServer("CMD"); + string procName = DataTestUtility.GetUniqueNameForSqlServer("CMD"); byte[] bArray = new byte[] { 1, 2, 3 }; using (var connection = new SqlConnection(DataTestUtility.TCPConnectionString))