From 0057c015c40c2e1e0e6a99f01b3e3f18dce5b9f5 Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Tue, 22 Jun 2021 20:28:44 +0100 Subject: [PATCH 01/18] merge --- .../Microsoft/Data/SqlClient/SqlCommand.cs | 3 +++ .../src/Microsoft/Data/SqlClient/TdsParser.cs | 20 +++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs index 238e5d7221..bad6fedfe6 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs @@ -740,6 +740,9 @@ public override UpdateRowSource UpdatedRowSource } } + /// + public bool UsePositionalParameters { get; set; } + /// public event StatementCompletedEventHandler StatementCompleted { diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs index 204b736715..7541ff0dbd 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs @@ -9021,7 +9021,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo if (mt.IsNewKatmaiType) { - WriteSmiParameter(param, i, 0 != (options & TdsEnums.RPC_PARAM_DEFAULT), stateObj, isAdvancedTraceOn); + WriteSmiParameter(param, i, 0 != (options & TdsEnums.RPC_PARAM_DEFAULT), stateObj, cmd.UsePositionalParameters, isAdvancedTraceOn); continue; } @@ -9031,7 +9031,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo throw ADP.VersionDoesNotSupportDataType(mt.TypeName); } - Task writeParamTask = TDSExecuteRPCAddParameter(stateObj, param, mt, options, cmd); + Task writeParamTask = TDSExecuteRPCAddParameter(stateObj, param, mt, options, cmd.UsePositionalParameters); if (!sync) { @@ -9148,7 +9148,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo } } - private Task TDSExecuteRPCAddParameter(TdsParserStateObject stateObj, SqlParameter param, MetaType mt, byte options, SqlCommand command) + private Task TDSExecuteRPCAddParameter(TdsParserStateObject stateObj, SqlParameter param, MetaType mt, byte options, bool isAnonymous) { int tempLen; object value = null; @@ -9173,7 +9173,7 @@ private Task TDSExecuteRPCAddParameter(TdsParserStateObject stateObj, SqlParamet } } - WriteParameterName(param.ParameterNameFixed, stateObj); + WriteParameterName(param.ParameterNameFixed, stateObj, isAnonymous); // Write parameter status stateObj.WriteByte(options); @@ -9695,11 +9695,11 @@ private void ExecuteFlushTaskCallback(Task tsk, TdsParserStateObject stateObj, T } - private void WriteParameterName(string parameterName, TdsParserStateObject stateObj) + private void WriteParameterName(string parameterName, TdsParserStateObject stateObj, bool isAnonymous) { // paramLen // paramName - if (!string.IsNullOrEmpty(parameterName)) + if (!isAnonymous && !string.IsNullOrEmpty(parameterName)) { Debug.Assert(parameterName.Length <= 0xff, "parameter name can only be 255 bytes, shouldn't get to TdsParser!"); int tempLen = parameterName.Length & 0xff; @@ -9712,7 +9712,7 @@ private void WriteParameterName(string parameterName, TdsParserStateObject state } } - private void WriteSmiParameter(SqlParameter param, int paramIndex, bool sendDefault, TdsParserStateObject stateObj, bool advancedTraceIsOn) + private void WriteSmiParameter(SqlParameter param, int paramIndex, bool sendDefault, TdsParserStateObject stateObj, bool isAnonymous, bool advancedTraceIsOn) { // // Determine Metadata @@ -9771,7 +9771,7 @@ private void WriteSmiParameter(SqlParameter param, int paramIndex, bool sendDefa // // Write parameter metadata // - WriteSmiParameterMetaData(metaData, sendDefault, stateObj); + WriteSmiParameterMetaData(metaData, sendDefault, isAnonymous, stateObj); // // Now write the value @@ -9790,7 +9790,7 @@ private void WriteSmiParameter(SqlParameter param, int paramIndex, bool sendDefa } // Writes metadata portion of parameter stream from an SmiParameterMetaData object. - private void WriteSmiParameterMetaData(SmiParameterMetaData metaData, bool sendDefault, TdsParserStateObject stateObj) + private void WriteSmiParameterMetaData(SmiParameterMetaData metaData, bool sendDefault, bool isAnonymous, TdsParserStateObject stateObj) { // Determine status byte status = 0; @@ -9805,7 +9805,7 @@ private void WriteSmiParameterMetaData(SmiParameterMetaData metaData, bool sendD } // Write everything out - WriteParameterName(metaData.Name, stateObj); + WriteParameterName(metaData.Name, stateObj, isAnonymous); stateObj.WriteByte(status); WriteSmiTypeInfo(metaData, stateObj); } From 372c15d29c493e74e02559d8835177365c967ff9 Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Sun, 18 Apr 2021 01:20:23 +0100 Subject: [PATCH 02/18] add netcore ref definition --- .../netcore/ref/Microsoft.Data.SqlClient.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs index 80069a220f..f1ea57ec65 100644 --- a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs +++ b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs @@ -544,6 +544,8 @@ public SqlCommand(string cmdText, Microsoft.Data.SqlClient.SqlConnection connect /// [System.ComponentModel.DefaultValueAttribute(3)] public override System.Data.UpdateRowSource UpdatedRowSource { get { throw null; } set { } } + /// + public bool UsePositionalParameters { get { throw null; } set { } } /// public event System.Data.StatementCompletedEventHandler StatementCompleted { add { } remove { } } /// From 3e43f8cf1d58b9131eba4d59da1d1a75461bf240 Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Sun, 18 Apr 2021 01:37:54 +0100 Subject: [PATCH 03/18] add netfx SqlCommand.UsePositionalParameters property --- .../src/Microsoft/Data/SqlClient/SqlCommand.cs | 3 +++ .../src/Microsoft/Data/SqlClient/TdsParser.cs | 16 ++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs index 19fd0902f3..f690ff8b58 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs @@ -954,6 +954,9 @@ public override UpdateRowSource UpdatedRowSource } } + /// + public bool UsePositionalParameters { get; set; } + /// [ ResCategoryAttribute(StringsHelper.ResourceNames.DataCategory_StatementCompleted), diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs index 92482d9e83..6eb104a182 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs @@ -9914,7 +9914,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo if (mt.IsNewKatmaiType) { - WriteSmiParameter(param, i, 0 != (rpcext.paramoptions[i] & TdsEnums.RPC_PARAM_DEFAULT), stateObj, isAdvancedTraceOn); + WriteSmiParameter(param, i, 0 != (rpcext.paramoptions[i] & TdsEnums.RPC_PARAM_DEFAULT), stateObj, cmd.UsePositionalParameters, isAdvancedTraceOn); continue; } @@ -9946,7 +9946,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo } } - WriteParameterName(param.ParameterNameFixed, stateObj); + WriteParameterName(param.ParameterNameFixed, stateObj, cmd.UsePositionalParameters); // Write parameter status stateObj.WriteByte(rpcext.paramoptions[i]); @@ -10628,11 +10628,11 @@ private void ExecuteFlushTaskCallback(Task tsk, TdsParserStateObject stateObj, T } - private void WriteParameterName(string parameterName, TdsParserStateObject stateObj) + private void WriteParameterName(string parameterName, TdsParserStateObject stateObj, bool isAnonymous) { // paramLen // paramName - if (!ADP.IsEmpty(parameterName)) + if (!isAnonymous && !string.IsNullOrEmpty(parameterName)) { Debug.Assert(parameterName.Length <= 0xff, "parameter name can only be 255 bytes, shouldn't get to TdsParser!"); int tempLen = parameterName.Length & 0xff; @@ -10646,7 +10646,7 @@ private void WriteParameterName(string parameterName, TdsParserStateObject state } private static readonly IEnumerable __tvpEmptyValue = new List().AsReadOnly(); - private void WriteSmiParameter(SqlParameter param, int paramIndex, bool sendDefault, TdsParserStateObject stateObj, bool advancedTraceIsOn) + private void WriteSmiParameter(SqlParameter param, int paramIndex, bool sendDefault, TdsParserStateObject stateObj, bool isAnonymous, bool advancedTraceIsOn) { // // Determine Metadata @@ -10706,7 +10706,7 @@ private void WriteSmiParameter(SqlParameter param, int paramIndex, bool sendDefa // // Write parameter metadata // - WriteSmiParameterMetaData(metaData, sendDefault, stateObj); + WriteSmiParameterMetaData(metaData, sendDefault, isAnonymous, stateObj); // // Now write the value @@ -10725,7 +10725,7 @@ private void WriteSmiParameter(SqlParameter param, int paramIndex, bool sendDefa } // Writes metadata portion of parameter stream from an SmiParameterMetaData object. - private void WriteSmiParameterMetaData(SmiParameterMetaData metaData, bool sendDefault, TdsParserStateObject stateObj) + private void WriteSmiParameterMetaData(SmiParameterMetaData metaData, bool sendDefault, bool isAnonymous, TdsParserStateObject stateObj) { // Determine status byte status = 0; @@ -10740,7 +10740,7 @@ private void WriteSmiParameterMetaData(SmiParameterMetaData metaData, bool sendD } // Write everything out - WriteParameterName(metaData.Name, stateObj); + WriteParameterName(metaData.Name, stateObj, isAnonymous); stateObj.WriteByte(status); WriteSmiTypeInfo(metaData, stateObj); } From 250bec51b8e5e0e844c64a6ed57fc6e39ae27b76 Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Sun, 18 Apr 2021 01:40:35 +0100 Subject: [PATCH 04/18] add netfx ref definition --- .../netfx/ref/Microsoft.Data.SqlClient.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs b/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs index 9b77d05d7e..6c3390dab0 100644 --- a/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs +++ b/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs @@ -565,6 +565,8 @@ public SqlCommand(string cmdText, Microsoft.Data.SqlClient.SqlConnection connect /// [System.ComponentModel.DefaultValueAttribute(3)] public override System.Data.UpdateRowSource UpdatedRowSource { get { throw null; } set { } } + /// + public bool UsePositionalParameters { get { throw null; } set { } } /// public event System.Data.StatementCompletedEventHandler StatementCompleted { add { } remove { } } /// From b84da27c9d4db7edb0f06b2e65bafc8ce17400ae Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Sun, 18 Apr 2021 23:02:23 +0100 Subject: [PATCH 05/18] add first set of tests --- .../SQL/ParameterTest/ParametersTest.cs | 175 ++++++++++++++++++ 1 file changed, 175 insertions(+) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs index b179b82d6a..26f42d24dd 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs @@ -520,5 +520,180 @@ private enum MyEnum A = 1, B = 2 } + + [Fact] + private static void PositionalParameters_ParametersAreUsedByPosition() + { + int firstInput = 1; + int secondInput = 2; + using (var connection = new SqlConnection(DataTestUtility.TCPConnectionString)) + { + connection.Open(); + + using (var command = new SqlCommand("SELECT @Second, @First", connection)) + { + command.UsePositionalParameters = true; + command.Parameters.AddWithValue("@First", firstInput); + command.Parameters.AddWithValue("@Second", secondInput); + + using (SqlDataReader reader = command.ExecuteReader()) + { + reader.Read(); + + int firstOutput = reader.GetInt32(0); + int secondOutput = reader.GetInt32(1); + + Assert.Equal(firstInput, secondOutput); + Assert.Equal(secondInput, firstOutput); + } + + } + } + } + + [Fact] + private static void PositionalParameters_NamesMustMatch() + { + using (var connection = new SqlConnection(DataTestUtility.TCPConnectionString)) + { + connection.Open(); + + using (var command = new SqlCommand("SELECT @DoesNotExist", connection)) + { + command.UsePositionalParameters = true; + command.Parameters.AddWithValue("@Exists", 1); + + SqlException sqlException = null; + try + { + command.ExecuteNonQuery(); + } + catch (SqlException sqlEx) + { + sqlException = sqlEx; + } + + Assert.NotNull(sqlException); + Assert.Contains("Must declare the scalar variable",sqlException.Message); + Assert.Contains("@DoesNotExist", sqlException.Message); + + } + } + } + + [Fact] + private static void PositionalParameters_AllNamesMustBeDeclared() + { + using (var connection = new SqlConnection(DataTestUtility.TCPConnectionString)) + { + connection.Open(); + + using (var command = new SqlCommand("SELECT @Exists, @DoesNotExist", connection)) + { + command.UsePositionalParameters = true; + command.Parameters.AddWithValue("@Exists", 1); + + SqlException sqlException = null; + try + { + command.ExecuteNonQuery(); + } + catch (SqlException sqlEx) + { + sqlException = sqlEx; + } + + Assert.NotNull(sqlException); + Assert.Contains("Must declare the scalar variable", sqlException.Message); + Assert.Contains("@DoesNotExist", sqlException.Message); + } + } + } + + [Fact] + private static void PositionalParameters_NamesCanBeReUsed() + { + int firstInput = 1; + int secondInput = 2; + int thirdInput = 3; + + using (var connection = new SqlConnection(DataTestUtility.TCPConnectionString)) + { + connection.Open(); + + using (var command = new SqlCommand("SELECT @First, @Second, @First", connection)) + { + command.UsePositionalParameters = true; + command.Parameters.AddWithValue("@First", firstInput); + command.Parameters.AddWithValue("@Second", secondInput); + command.Parameters.AddWithValue("@Third", thirdInput); + + using (SqlDataReader reader = command.ExecuteReader()) + { + reader.Read(); + + int firstOutput = reader.GetInt32(0); + int secondOutput = reader.GetInt32(1); + int thirdOutput = reader.GetInt32(2); + + Assert.Equal(firstInput, firstOutput); + Assert.Equal(secondInput, secondOutput); + Assert.Equal(firstInput, thirdOutput); + } + } + } + } + + [Fact] + private static void PositionalParameters_InputOutputFails() + { + int firstInput = 1; + int secondInput = 2; + int thirdInput = 3; + + using (var connection = new SqlConnection(DataTestUtility.TCPConnectionString)) + { + connection.Open(); + + using (var command = new SqlCommand("SELECT @Third = (@Third + @First + @Second)", connection)) + { + command.UsePositionalParameters = true; + command.Parameters.AddWithValue("@First", firstInput); + command.Parameters.AddWithValue("@Second", secondInput); + SqlParameter thirdParameter = command.Parameters.AddWithValue("@Third", thirdInput); + thirdParameter.Direction = ParameterDirection.InputOutput; + + command.ExecuteNonQuery(); + + Assert.Equal(thirdInput, Convert.ToInt32(thirdParameter.Value)); + } + } + } + + [Fact] + private static void PositionalParameters_OutputFails() + { + int firstInput = 1; + int secondInput = 2; + int thirdInput = 3; + + using (var connection = new SqlConnection(DataTestUtility.TCPConnectionString)) + { + connection.Open(); + + using (var command = new SqlCommand("SELECT @Third = (@Third + @First + @Second)", connection)) + { + command.UsePositionalParameters = true; + command.Parameters.AddWithValue("@First", firstInput); + command.Parameters.AddWithValue("@Second", secondInput); + SqlParameter thirdParameter = command.Parameters.AddWithValue("@Third", thirdInput); + thirdParameter.Direction = ParameterDirection.Output; + + command.ExecuteNonQuery(); + + Assert.Equal(0, Convert.ToInt32(thirdParameter.Value)); + } + } + } } } From a553c1b517774c7f707232751dcd06c2991edd9c Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Mon, 19 Apr 2021 00:38:13 +0100 Subject: [PATCH 06/18] add return test --- .../SQL/ParameterTest/ParametersTest.cs | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs index 26f42d24dd..37af426664 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs @@ -521,6 +521,17 @@ private enum MyEnum B = 2 } + private static void ExecuteNonQueryCommand(string connectionString, string cmdText) + { + using (SqlConnection conn = new SqlConnection(connectionString)) + using (SqlCommand cmd = conn.CreateCommand()) + { + conn.Open(); + cmd.CommandText = cmdText; + cmd.ExecuteNonQuery(); + } + } + [Fact] private static void PositionalParameters_ParametersAreUsedByPosition() { @@ -695,5 +706,46 @@ private static void PositionalParameters_OutputFails() } } } + + [Fact] + private static void PositionalParameters_ReturnSucceeds() + { + int firstInput = 12; + + string sprocName = DataTestUtility.GetUniqueName("P"); + // input, output + string createSprocQuery = + "CREATE PROCEDURE " + sprocName + " @in int " + + "AS " + + "RETURN(@in)"; + + string dropSprocQuery = "DROP PROCEDURE " + sprocName; + + try + { + ExecuteNonQueryCommand(DataTestUtility.TCPConnectionString, createSprocQuery); + + using (var connection = new SqlConnection(DataTestUtility.TCPConnectionString)) + { + connection.Open(); + + using (var command = new SqlCommand(sprocName, connection) { CommandType = CommandType.StoredProcedure }) + { + command.UsePositionalParameters = true; + command.Parameters.AddWithValue("@in", firstInput); + SqlParameter returnParameter = command.Parameters.AddWithValue("@retval", 0); + returnParameter.Direction = ParameterDirection.ReturnValue; + + command.ExecuteNonQuery(); + + Assert.Equal(firstInput, Convert.ToInt32(returnParameter.Value)); + } + } + } + finally + { + ExecuteNonQueryCommand(DataTestUtility.TCPConnectionString, dropSprocQuery); + } + } } } From 1f88591b43fd9b1e2ee2bcf028088335c2354732 Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Mon, 19 Apr 2021 20:26:37 +0100 Subject: [PATCH 07/18] renamed to DisableOutputParameters --- .../netcore/ref/Microsoft.Data.SqlClient.cs | 4 +-- .../Microsoft/Data/SqlClient/SqlCommand.cs | 6 ++-- .../src/Microsoft/Data/SqlClient/TdsParser.cs | 4 +-- .../netfx/ref/Microsoft.Data.SqlClient.cs | 4 +-- .../Microsoft/Data/SqlClient/SqlCommand.cs | 6 ++-- .../src/Microsoft/Data/SqlClient/TdsParser.cs | 4 +-- .../SQL/ParameterTest/ParametersTest.cs | 28 +++++++++---------- 7 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs index f1ea57ec65..1741b487dc 100644 --- a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs +++ b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs @@ -535,6 +535,8 @@ public SqlCommand(string cmdText, Microsoft.Data.SqlClient.SqlConnection connect [System.ComponentModel.DesignOnlyAttribute(true)] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public override bool DesignTimeVisible { get { throw null; } set { } } + /// + public bool DisableOutputParameters { get { throw null; } set { } } /// public new Microsoft.Data.SqlClient.SqlParameterCollection Parameters { get { throw null; } } /// @@ -544,8 +546,6 @@ public SqlCommand(string cmdText, Microsoft.Data.SqlClient.SqlConnection connect /// [System.ComponentModel.DefaultValueAttribute(3)] public override System.Data.UpdateRowSource UpdatedRowSource { get { throw null; } set { } } - /// - public bool UsePositionalParameters { get { throw null; } set { } } /// public event System.Data.StatementCompletedEventHandler StatementCompleted { add { } remove { } } /// diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs index bad6fedfe6..bc650d8d48 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs @@ -692,6 +692,9 @@ public override bool DesignTimeVisible } } + /// + public bool DisableOutputParameters { get; set; } + /// new public SqlParameterCollection Parameters { @@ -740,9 +743,6 @@ public override UpdateRowSource UpdatedRowSource } } - /// - public bool UsePositionalParameters { get; set; } - /// public event StatementCompletedEventHandler StatementCompleted { diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs index 7541ff0dbd..36edf9cfd9 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs @@ -9021,7 +9021,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo if (mt.IsNewKatmaiType) { - WriteSmiParameter(param, i, 0 != (options & TdsEnums.RPC_PARAM_DEFAULT), stateObj, cmd.UsePositionalParameters, isAdvancedTraceOn); + WriteSmiParameter(param, i, 0 != (options & TdsEnums.RPC_PARAM_DEFAULT), stateObj, cmd.DisableOutputParameters, isAdvancedTraceOn); continue; } @@ -9031,7 +9031,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo throw ADP.VersionDoesNotSupportDataType(mt.TypeName); } - Task writeParamTask = TDSExecuteRPCAddParameter(stateObj, param, mt, options, cmd.UsePositionalParameters); + Task writeParamTask = TDSExecuteRPCAddParameter(stateObj, param, mt, options, cmd.DisableOutputParameters); if (!sync) { diff --git a/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs b/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs index 6c3390dab0..7cd064ba9f 100644 --- a/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs +++ b/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs @@ -556,6 +556,8 @@ public SqlCommand(string cmdText, Microsoft.Data.SqlClient.SqlConnection connect [System.ComponentModel.DesignOnlyAttribute(true)] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public override bool DesignTimeVisible { get { throw null; } set { } } + /// + public bool DisableOutputParameters { get { throw null; } set { } } /// public new Microsoft.Data.SqlClient.SqlParameterCollection Parameters { get { throw null; } } /// @@ -565,8 +567,6 @@ public SqlCommand(string cmdText, Microsoft.Data.SqlClient.SqlConnection connect /// [System.ComponentModel.DefaultValueAttribute(3)] public override System.Data.UpdateRowSource UpdatedRowSource { get { throw null; } set { } } - /// - public bool UsePositionalParameters { get { throw null; } set { } } /// public event System.Data.StatementCompletedEventHandler StatementCompleted { add { } remove { } } /// diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs index f690ff8b58..7c67fef257 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs @@ -880,6 +880,9 @@ public override bool DesignTimeVisible } } + /// + public bool DisableOutputParameters { get; set; } + /// [ DesignerSerializationVisibility(DesignerSerializationVisibility.Content), @@ -954,9 +957,6 @@ public override UpdateRowSource UpdatedRowSource } } - /// - public bool UsePositionalParameters { get; set; } - /// [ ResCategoryAttribute(StringsHelper.ResourceNames.DataCategory_StatementCompleted), diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs index 6eb104a182..321c343eb0 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs @@ -9914,7 +9914,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo if (mt.IsNewKatmaiType) { - WriteSmiParameter(param, i, 0 != (rpcext.paramoptions[i] & TdsEnums.RPC_PARAM_DEFAULT), stateObj, cmd.UsePositionalParameters, isAdvancedTraceOn); + WriteSmiParameter(param, i, 0 != (rpcext.paramoptions[i] & TdsEnums.RPC_PARAM_DEFAULT), stateObj, cmd.DisableOutputParameters, isAdvancedTraceOn); continue; } @@ -9946,7 +9946,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo } } - WriteParameterName(param.ParameterNameFixed, stateObj, cmd.UsePositionalParameters); + WriteParameterName(param.ParameterNameFixed, stateObj, cmd.DisableOutputParameters); // Write parameter status stateObj.WriteByte(rpcext.paramoptions[i]); diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs index 37af426664..4e81b57c78 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs @@ -533,7 +533,7 @@ private static void ExecuteNonQueryCommand(string connectionString, string cmdTe } [Fact] - private static void PositionalParameters_ParametersAreUsedByPosition() + private static void DisableOutputParameters_ParametersAreUsedByName() { int firstInput = 1; int secondInput = 2; @@ -543,7 +543,7 @@ private static void PositionalParameters_ParametersAreUsedByPosition() using (var command = new SqlCommand("SELECT @Second, @First", connection)) { - command.UsePositionalParameters = true; + command.DisableOutputParameters = true; command.Parameters.AddWithValue("@First", firstInput); command.Parameters.AddWithValue("@Second", secondInput); @@ -563,7 +563,7 @@ private static void PositionalParameters_ParametersAreUsedByPosition() } [Fact] - private static void PositionalParameters_NamesMustMatch() + private static void DisableOutputParameters_NamesMustMatch() { using (var connection = new SqlConnection(DataTestUtility.TCPConnectionString)) { @@ -571,7 +571,7 @@ private static void PositionalParameters_NamesMustMatch() using (var command = new SqlCommand("SELECT @DoesNotExist", connection)) { - command.UsePositionalParameters = true; + command.DisableOutputParameters = true; command.Parameters.AddWithValue("@Exists", 1); SqlException sqlException = null; @@ -593,7 +593,7 @@ private static void PositionalParameters_NamesMustMatch() } [Fact] - private static void PositionalParameters_AllNamesMustBeDeclared() + private static void DisableOutputParameters_AllNamesMustBeDeclared() { using (var connection = new SqlConnection(DataTestUtility.TCPConnectionString)) { @@ -601,7 +601,7 @@ private static void PositionalParameters_AllNamesMustBeDeclared() using (var command = new SqlCommand("SELECT @Exists, @DoesNotExist", connection)) { - command.UsePositionalParameters = true; + command.DisableOutputParameters = true; command.Parameters.AddWithValue("@Exists", 1); SqlException sqlException = null; @@ -622,7 +622,7 @@ private static void PositionalParameters_AllNamesMustBeDeclared() } [Fact] - private static void PositionalParameters_NamesCanBeReUsed() + private static void DisableOutputParameters_NamesCanBeReUsed() { int firstInput = 1; int secondInput = 2; @@ -634,7 +634,7 @@ private static void PositionalParameters_NamesCanBeReUsed() using (var command = new SqlCommand("SELECT @First, @Second, @First", connection)) { - command.UsePositionalParameters = true; + command.DisableOutputParameters = true; command.Parameters.AddWithValue("@First", firstInput); command.Parameters.AddWithValue("@Second", secondInput); command.Parameters.AddWithValue("@Third", thirdInput); @@ -656,7 +656,7 @@ private static void PositionalParameters_NamesCanBeReUsed() } [Fact] - private static void PositionalParameters_InputOutputFails() + private static void DisableOutputParameters_InputOutputFails() { int firstInput = 1; int secondInput = 2; @@ -668,7 +668,7 @@ private static void PositionalParameters_InputOutputFails() using (var command = new SqlCommand("SELECT @Third = (@Third + @First + @Second)", connection)) { - command.UsePositionalParameters = true; + command.DisableOutputParameters = true; command.Parameters.AddWithValue("@First", firstInput); command.Parameters.AddWithValue("@Second", secondInput); SqlParameter thirdParameter = command.Parameters.AddWithValue("@Third", thirdInput); @@ -682,7 +682,7 @@ private static void PositionalParameters_InputOutputFails() } [Fact] - private static void PositionalParameters_OutputFails() + private static void DisableOutputParameters_OutputFails() { int firstInput = 1; int secondInput = 2; @@ -694,7 +694,7 @@ private static void PositionalParameters_OutputFails() using (var command = new SqlCommand("SELECT @Third = (@Third + @First + @Second)", connection)) { - command.UsePositionalParameters = true; + command.DisableOutputParameters = true; command.Parameters.AddWithValue("@First", firstInput); command.Parameters.AddWithValue("@Second", secondInput); SqlParameter thirdParameter = command.Parameters.AddWithValue("@Third", thirdInput); @@ -708,7 +708,7 @@ private static void PositionalParameters_OutputFails() } [Fact] - private static void PositionalParameters_ReturnSucceeds() + private static void DisableOutputParameters_ReturnSucceeds() { int firstInput = 12; @@ -731,7 +731,7 @@ private static void PositionalParameters_ReturnSucceeds() using (var command = new SqlCommand(sprocName, connection) { CommandType = CommandType.StoredProcedure }) { - command.UsePositionalParameters = true; + command.DisableOutputParameters = true; command.Parameters.AddWithValue("@in", firstInput); SqlParameter returnParameter = command.Parameters.AddWithValue("@retval", 0); returnParameter.Direction = ParameterDirection.ReturnValue; From afb5050b22314a8e7708ca84bb1d29da35c4c4cd Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Tue, 22 Jun 2021 20:30:51 +0100 Subject: [PATCH 08/18] merge --- .../src/Microsoft/Data/SqlClient/SqlCommand.cs | 4 ++-- .../src/Microsoft/Data/SqlClient/SqlUtil.cs | 5 +++++ .../src/Microsoft/Data/SqlClient/TdsParser.cs | 16 +++++++++++++--- .../netcore/src/Resources/Strings.Designer.cs | 9 +++++++++ .../netcore/src/Resources/Strings.resx | 3 +++ 5 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs index bc650d8d48..0b6cc4abf8 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlCommand.cs @@ -692,8 +692,8 @@ public override bool DesignTimeVisible } } - /// - public bool DisableOutputParameters { get; set; } + /// + public bool EnableOptimizedParameterBinding { get; set; } /// new public SqlParameterCollection Parameters diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlUtil.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlUtil.cs index 46c874ab80..745e820948 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlUtil.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/SqlUtil.cs @@ -495,6 +495,11 @@ internal static Exception ParameterCannotBeEmpty(string paramName) return ADP.ArgumentNull(System.StringsHelper.GetString(Strings.SQL_ParameterCannotBeEmpty, paramName)); } + internal static Exception ParameterDirectionInvalidForOptimizedBinding(string paramName) + { + return ADP.InvalidOperation(System.StringsHelper.GetString(Strings.SQL_ParameterDirectionInvalidForOptimizedBinding, paramName)); + } + internal static Exception ActiveDirectoryInteractiveTimeout() { return ADP.TimeoutException(Strings.SQL_Timeout_Active_Directory_Interactive_Authentication); diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs index 36edf9cfd9..3247e3b79b 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs @@ -8988,6 +8988,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo int parametersLength = rpcext.userParamCount + rpcext.systemParamCount; bool isAdvancedTraceOn = SqlClientEventSource.Log.IsAdvancedTraceOn(); + bool enableOptimizedParameterBinding = cmd.EnableOptimizedParameterBinding; for (int i = (ii == startRpc) ? startParam : 0; i < parametersLength; i++) { @@ -8995,7 +8996,11 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo SqlParameter param = rpcext.GetParameterByIndex(i, out options); // Since we are reusing the parameters array, we cannot rely on length to indicate no of parameters. if (param == null) + { break; // End of parameters for this execute + } + + ParameterDirection parameterDirection = param.Direction; // Throw an exception if ForceColumnEncryption is set on a parameter and the ColumnEncryption is not enabled on SqlConnection or SqlCommand if (param.ForceColumnEncryption && @@ -9007,12 +9012,17 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo // Check if the applications wants to force column encryption to avoid sending sensitive data to server if (param.ForceColumnEncryption && param.CipherMetadata == null - && (param.Direction == ParameterDirection.Input || param.Direction == ParameterDirection.InputOutput)) + && (parameterDirection == ParameterDirection.Input || parameterDirection == ParameterDirection.InputOutput)) { // Application wants a parameter to be encrypted before sending it to server, however server doesnt think this parameter needs encryption. throw SQL.ParamUnExpectedEncryptionMetadata(param.ParameterName, rpcext.GetCommandTextOrRpcName()); } + if (enableOptimizedParameterBinding && (parameterDirection == ParameterDirection.Output || parameterDirection == ParameterDirection.InputOutput)) + { + throw SQL.ParameterDirectionInvalidForOptimizedBinding(param.ParameterName); + } + // Validate parameters are not variable length without size and with null value. param.Validate(i, isCommandProc); @@ -9021,7 +9031,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo if (mt.IsNewKatmaiType) { - WriteSmiParameter(param, i, 0 != (options & TdsEnums.RPC_PARAM_DEFAULT), stateObj, cmd.DisableOutputParameters, isAdvancedTraceOn); + WriteSmiParameter(param, i, 0 != (options & TdsEnums.RPC_PARAM_DEFAULT), stateObj, enableOptimizedParameterBinding, isAdvancedTraceOn); continue; } @@ -9031,7 +9041,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo throw ADP.VersionDoesNotSupportDataType(mt.TypeName); } - Task writeParamTask = TDSExecuteRPCAddParameter(stateObj, param, mt, options, cmd.DisableOutputParameters); + Task writeParamTask = TDSExecuteRPCAddParameter(stateObj, param, mt, options, enableOptimizedParameterBinding); if (!sync) { diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.Designer.cs b/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.Designer.cs index e043593408..5f81a9cbcc 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.Designer.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.Designer.cs @@ -2931,6 +2931,15 @@ internal static string SQL_ParameterCannotBeEmpty { } } + /// + /// Looks up a localized string similar to Parameter '{0}' cannot have Direction Output or InputOutput when EnableOptimizedParameterBinding is enabled on the parent command.. + /// + internal static string SQL_ParameterDirectionInvalidForOptimizedBinding { + get { + return ResourceManager.GetString("SQL_ParameterDirectionInvalidForOptimizedBinding", resourceCulture); + } + } + /// /// Looks up a localized string similar to Parameter '{0}' exceeds the size limit for the sql_variant datatype.. /// diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.resx b/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.resx index 14a70b74a3..4dff81e444 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.resx +++ b/src/Microsoft.Data.SqlClient/netcore/src/Resources/Strings.resx @@ -1932,4 +1932,7 @@ '{0}' is not less than '{1}'; '{2}' cannot be greater than '{3}'. + + Parameter '{0}' cannot have Direction Output or InputOutput when EnableOptimizedParameterBinding is enabled on the parent command. + \ No newline at end of file From 34e552e6d6635dab50df61abc56bc8e2dd53261d Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Tue, 4 May 2021 01:14:42 +0100 Subject: [PATCH 09/18] tests changes --- .../SQL/ParameterTest/ParametersTest.cs | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs index 4e81b57c78..a856aeb8aa 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs @@ -533,7 +533,7 @@ private static void ExecuteNonQueryCommand(string connectionString, string cmdTe } [Fact] - private static void DisableOutputParameters_ParametersAreUsedByName() + private static void EnableOptimizedParameterBinding_ParametersAreUsedByName() { int firstInput = 1; int secondInput = 2; @@ -543,7 +543,7 @@ private static void DisableOutputParameters_ParametersAreUsedByName() using (var command = new SqlCommand("SELECT @Second, @First", connection)) { - command.DisableOutputParameters = true; + command.EnableOptimizedParameterBinding = true; command.Parameters.AddWithValue("@First", firstInput); command.Parameters.AddWithValue("@Second", secondInput); @@ -563,7 +563,7 @@ private static void DisableOutputParameters_ParametersAreUsedByName() } [Fact] - private static void DisableOutputParameters_NamesMustMatch() + private static void EnableOptimizedParameterBinding_NamesMustMatch() { using (var connection = new SqlConnection(DataTestUtility.TCPConnectionString)) { @@ -571,7 +571,7 @@ private static void DisableOutputParameters_NamesMustMatch() using (var command = new SqlCommand("SELECT @DoesNotExist", connection)) { - command.DisableOutputParameters = true; + command.EnableOptimizedParameterBinding = true; command.Parameters.AddWithValue("@Exists", 1); SqlException sqlException = null; @@ -593,7 +593,7 @@ private static void DisableOutputParameters_NamesMustMatch() } [Fact] - private static void DisableOutputParameters_AllNamesMustBeDeclared() + private static void EnableOptimizedParameterBinding_AllNamesMustBeDeclared() { using (var connection = new SqlConnection(DataTestUtility.TCPConnectionString)) { @@ -601,7 +601,7 @@ private static void DisableOutputParameters_AllNamesMustBeDeclared() using (var command = new SqlCommand("SELECT @Exists, @DoesNotExist", connection)) { - command.DisableOutputParameters = true; + command.EnableOptimizedParameterBinding = true; command.Parameters.AddWithValue("@Exists", 1); SqlException sqlException = null; @@ -622,7 +622,7 @@ private static void DisableOutputParameters_AllNamesMustBeDeclared() } [Fact] - private static void DisableOutputParameters_NamesCanBeReUsed() + private static void EnableOptimizedParameterBinding_NamesCanBeReUsed() { int firstInput = 1; int secondInput = 2; @@ -634,7 +634,7 @@ private static void DisableOutputParameters_NamesCanBeReUsed() using (var command = new SqlCommand("SELECT @First, @Second, @First", connection)) { - command.DisableOutputParameters = true; + command.EnableOptimizedParameterBinding = true; command.Parameters.AddWithValue("@First", firstInput); command.Parameters.AddWithValue("@Second", secondInput); command.Parameters.AddWithValue("@Third", thirdInput); @@ -656,7 +656,7 @@ private static void DisableOutputParameters_NamesCanBeReUsed() } [Fact] - private static void DisableOutputParameters_InputOutputFails() + private static void EnableOptimizedParameterBinding_InputOutputFails() { int firstInput = 1; int secondInput = 2; @@ -668,21 +668,21 @@ private static void DisableOutputParameters_InputOutputFails() using (var command = new SqlCommand("SELECT @Third = (@Third + @First + @Second)", connection)) { - command.DisableOutputParameters = true; + command.EnableOptimizedParameterBinding = true; command.Parameters.AddWithValue("@First", firstInput); command.Parameters.AddWithValue("@Second", secondInput); SqlParameter thirdParameter = command.Parameters.AddWithValue("@Third", thirdInput); thirdParameter.Direction = ParameterDirection.InputOutput; - command.ExecuteNonQuery(); + InvalidOperationException exception = Assert.Throws(() => command.ExecuteNonQuery()); - Assert.Equal(thirdInput, Convert.ToInt32(thirdParameter.Value)); + Assert.Contains("OptimizedParameterBinding", exception.Message); } } } [Fact] - private static void DisableOutputParameters_OutputFails() + private static void EnableOptimizedParameterBinding_OutputFails() { int firstInput = 1; int secondInput = 2; @@ -694,21 +694,21 @@ private static void DisableOutputParameters_OutputFails() using (var command = new SqlCommand("SELECT @Third = (@Third + @First + @Second)", connection)) { - command.DisableOutputParameters = true; + command.EnableOptimizedParameterBinding = true; command.Parameters.AddWithValue("@First", firstInput); command.Parameters.AddWithValue("@Second", secondInput); SqlParameter thirdParameter = command.Parameters.AddWithValue("@Third", thirdInput); thirdParameter.Direction = ParameterDirection.Output; - command.ExecuteNonQuery(); + InvalidOperationException exception = Assert.Throws(() => command.ExecuteNonQuery()); - Assert.Equal(0, Convert.ToInt32(thirdParameter.Value)); + Assert.Contains("OptimizedParameterBinding", exception.Message); } } } [Fact] - private static void DisableOutputParameters_ReturnSucceeds() + private static void EnableOptimizedParameterBinding_ReturnSucceeds() { int firstInput = 12; @@ -731,7 +731,7 @@ private static void DisableOutputParameters_ReturnSucceeds() using (var command = new SqlCommand(sprocName, connection) { CommandType = CommandType.StoredProcedure }) { - command.DisableOutputParameters = true; + command.EnableOptimizedParameterBinding = true; command.Parameters.AddWithValue("@in", firstInput); SqlParameter returnParameter = command.Parameters.AddWithValue("@retval", 0); returnParameter.Direction = ParameterDirection.ReturnValue; From 206d30d3117b30fb8702cd1c13c7f90b4aa8df6b Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Tue, 4 May 2021 21:10:57 +0100 Subject: [PATCH 10/18] add documentation --- .../Microsoft.Data.SqlClient/SqlCommand.xml | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml index 68b10ce395..0738039d4a 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml @@ -1343,6 +1343,33 @@ The method is a st To be added. + + + Gets or sets a value indicating whether the command object should optimize parameter performance by disabling Output and InputOutput directions when submitting the command to the SQL Server. + + + A value indicating whether the command object should optimize parameter performance by disabling Output and InputOuput parameter directions when submitting the command to the SQL Server. + The default is . + + + + [!NOTE] +If the option is enabled and a parameter with Direction Output or InputOutput is present in the Parameters collection an InvalidOperationException will be thrown when the command is executed. + +]]> + + + The From 4f465fa447d67bf0d530de2b0d0f0cb70235c3a2 Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Tue, 22 Jun 2021 21:08:48 +0100 Subject: [PATCH 11/18] fixup merge conflicts --- .../netcore/src/Microsoft/Data/SqlClient/TdsParser.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs index 3247e3b79b..cb55efbee1 100644 --- a/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs +++ b/src/Microsoft.Data.SqlClient/netcore/src/Microsoft/Data/SqlClient/TdsParser.cs @@ -9041,7 +9041,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo throw ADP.VersionDoesNotSupportDataType(mt.TypeName); } - Task writeParamTask = TDSExecuteRPCAddParameter(stateObj, param, mt, options, enableOptimizedParameterBinding); + Task writeParamTask = TDSExecuteRPCAddParameter(stateObj, param, mt, options, cmd, enableOptimizedParameterBinding); if (!sync) { @@ -9158,7 +9158,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo } } - private Task TDSExecuteRPCAddParameter(TdsParserStateObject stateObj, SqlParameter param, MetaType mt, byte options, bool isAnonymous) + private Task TDSExecuteRPCAddParameter(TdsParserStateObject stateObj, SqlParameter param, MetaType mt, byte options, SqlCommand command, bool isAnonymous) { int tempLen; object value = null; From aa1b1f8617515ea6d36f3b2e2b1e31032a1268bb Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Tue, 22 Jun 2021 21:33:05 +0100 Subject: [PATCH 12/18] consistant naming --- .../netcore/ref/Microsoft.Data.SqlClient.cs | 4 ++-- .../netfx/ref/Microsoft.Data.SqlClient.cs | 4 ++-- .../netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs | 4 ++-- .../netfx/src/Microsoft/Data/SqlClient/TdsParser.cs | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs index 1741b487dc..621dc0a24b 100644 --- a/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs +++ b/src/Microsoft.Data.SqlClient/netcore/ref/Microsoft.Data.SqlClient.cs @@ -535,8 +535,8 @@ public SqlCommand(string cmdText, Microsoft.Data.SqlClient.SqlConnection connect [System.ComponentModel.DesignOnlyAttribute(true)] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public override bool DesignTimeVisible { get { throw null; } set { } } - /// - public bool DisableOutputParameters { get { throw null; } set { } } + /// + public bool EnableOptimizedParameterBinding { get { throw null; } set { } } /// public new Microsoft.Data.SqlClient.SqlParameterCollection Parameters { get { throw null; } } /// diff --git a/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs b/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs index 7cd064ba9f..587fe46862 100644 --- a/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs +++ b/src/Microsoft.Data.SqlClient/netfx/ref/Microsoft.Data.SqlClient.cs @@ -556,8 +556,8 @@ public SqlCommand(string cmdText, Microsoft.Data.SqlClient.SqlConnection connect [System.ComponentModel.DesignOnlyAttribute(true)] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public override bool DesignTimeVisible { get { throw null; } set { } } - /// - public bool DisableOutputParameters { get { throw null; } set { } } + /// + public bool EnableOptimizedParameterBinding { get { throw null; } set { } } /// public new Microsoft.Data.SqlClient.SqlParameterCollection Parameters { get { throw null; } } /// diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs index 7c67fef257..c9bb7ece07 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlCommand.cs @@ -880,8 +880,8 @@ public override bool DesignTimeVisible } } - /// - public bool DisableOutputParameters { get; set; } + /// + public bool EnableOptimizedParameterBinding { get; set; } /// [ diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs index 321c343eb0..f753fafed3 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs @@ -9914,7 +9914,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo if (mt.IsNewKatmaiType) { - WriteSmiParameter(param, i, 0 != (rpcext.paramoptions[i] & TdsEnums.RPC_PARAM_DEFAULT), stateObj, cmd.DisableOutputParameters, isAdvancedTraceOn); + WriteSmiParameter(param, i, 0 != (rpcext.paramoptions[i] & TdsEnums.RPC_PARAM_DEFAULT), stateObj, cmd.EnableOptimizedParameterBinding, isAdvancedTraceOn); continue; } @@ -9946,7 +9946,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo } } - WriteParameterName(param.ParameterNameFixed, stateObj, cmd.DisableOutputParameters); + WriteParameterName(param.ParameterNameFixed, stateObj, cmd.EnableOptimizedParameterBinding); // Write parameter status stateObj.WriteByte(rpcext.paramoptions[i]); From d6c66a100933f2966dff14c6b53cf785f29f5b7f Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Tue, 22 Jun 2021 21:48:53 +0100 Subject: [PATCH 13/18] sync netcore and netfx implementations --- .../src/Microsoft/Data/SqlClient/SqlUtil.cs | 5 ++ .../src/Microsoft/Data/SqlClient/TdsParser.cs | 18 ++++- .../netfx/src/Resources/Strings.Designer.cs | 78 +++++++++++-------- .../netfx/src/Resources/Strings.resx | 5 +- 4 files changed, 68 insertions(+), 38 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlUtil.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlUtil.cs index 868f9eaf9a..3496c68776 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlUtil.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/SqlUtil.cs @@ -636,6 +636,11 @@ static internal Exception ParameterCannotBeEmpty(string paramName) return ADP.ArgumentNull(StringsHelper.GetString(Strings.SQL_ParameterCannotBeEmpty, paramName)); } + internal static Exception ParameterDirectionInvalidForOptimizedBinding(string paramName) + { + return ADP.InvalidOperation(StringsHelper.GetString(Strings.SQL_ParameterDirectionInvalidForOptimizedBinding, paramName)); + } + static internal Exception ActiveDirectoryInteractiveTimeout() { return ADP.TimeoutException(Strings.SQL_Timeout_Active_Directory_Interactive_Authentication); diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs index f753fafed3..14822bedf2 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Microsoft/Data/SqlClient/TdsParser.cs @@ -9880,6 +9880,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo SqlParameter[] parameters = rpcext.parameters; bool isAdvancedTraceOn = SqlClientEventSource.Log.IsAdvancedTraceOn(); + bool enableOptimizedParameterBinding = cmd.EnableOptimizedParameterBinding; for (int i = (ii == startRpc) ? startParam : 0; i < parameters.Length; i++) { @@ -9888,7 +9889,11 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo SqlParameter param = parameters[i]; // Since we are reusing the parameters array, we cannot rely on length to indicate no of parameters. if (param == null) + { break; // End of parameters for this execute + } + + ParameterDirection parameterDirection = param.Direction; // Throw an exception if ForceColumnEncryption is set on a parameter and the ColumnEncryption is not enabled on SqlConnection or SqlCommand if (param.ForceColumnEncryption && @@ -9900,12 +9905,17 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo // Check if the applications wants to force column encryption to avoid sending sensitive data to server if (param.ForceColumnEncryption && param.CipherMetadata == null - && (param.Direction == ParameterDirection.Input || param.Direction == ParameterDirection.InputOutput)) + && (parameterDirection == ParameterDirection.Input || parameterDirection == ParameterDirection.InputOutput)) { // Application wants a parameter to be encrypted before sending it to server, however server doesnt think this parameter needs encryption. throw SQL.ParamUnExpectedEncryptionMetadata(param.ParameterName, rpcext.GetCommandTextOrRpcName()); } + if (enableOptimizedParameterBinding && (parameterDirection == ParameterDirection.Output || parameterDirection == ParameterDirection.InputOutput)) + { + throw SQL.ParameterDirectionInvalidForOptimizedBinding(param.ParameterName); + } + // Validate parameters are not variable length without size and with null value. MDAC 66522 param.Validate(i, isCommandProc); @@ -9914,7 +9924,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo if (mt.IsNewKatmaiType) { - WriteSmiParameter(param, i, 0 != (rpcext.paramoptions[i] & TdsEnums.RPC_PARAM_DEFAULT), stateObj, cmd.EnableOptimizedParameterBinding, isAdvancedTraceOn); + WriteSmiParameter(param, i, 0 != (rpcext.paramoptions[i] & TdsEnums.RPC_PARAM_DEFAULT), stateObj, enableOptimizedParameterBinding, isAdvancedTraceOn); continue; } @@ -9929,7 +9939,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo bool isSqlVal = false; bool isDataFeed = false; // if we have an output param, set the value to null so we do not send it across to the server - if (param.Direction == ParameterDirection.Output) + if (parameterDirection == ParameterDirection.Output) { isSqlVal = param.ParameterIsSqlType; // We have to forward the TYPE info, we need to know what type we are returning. Once we null the parameter we will no longer be able to distinguish what type were seeing. param.Value = null; @@ -9946,7 +9956,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo } } - WriteParameterName(param.ParameterNameFixed, stateObj, cmd.EnableOptimizedParameterBinding); + WriteParameterName(param.ParameterNameFixed, stateObj, enableOptimizedParameterBinding); // Write parameter status stateObj.WriteByte(rpcext.paramoptions[i]); diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.Designer.cs b/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.Designer.cs index bf23167d40..69a84e09c8 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.Designer.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.Designer.cs @@ -1824,15 +1824,6 @@ internal static string ADP_VersionDoesNotSupportDataType { } } - /// - /// Looks up a localized string similar to The validation of an attestation token failed. The token signature does not match the signature omputed using a public key retrieved from the attestation public key endpoint at '{0}'. Verify the DNS apping for the endpoint - see https://go.microsoft.com/fwlink/?linkid=2157649 for more details. If correct, contact Customer Support Services.. - /// - internal static string AttestationTokenSignatureValidationFailed { - get { - return ResourceManager.GetString("AttestationTokenSignatureValidationFailed", resourceCulture); - } - } - /// /// Looks up a localized string similar to Destination array is not long enough to copy all the items in the collection. Check array index and length.. /// @@ -1869,6 +1860,15 @@ internal static string ArgumentOutOfRange_NeedNonNegNum { } } + /// + /// Looks up a localized string similar to The validation of an attestation token failed. The token signature does not match the signature omputed using a public key retrieved from the attestation public key endpoint at '{0}'. Verify the DNS apping for the endpoint - see https://go.microsoft.com/fwlink/?linkid=2157649 for more details. If correct, contact Customer Support Services.. + /// + internal static string AttestationTokenSignatureValidationFailed { + get { + return ResourceManager.GetString("AttestationTokenSignatureValidationFailed", resourceCulture); + } + } + /// /// Looks up a localized string similar to .database.chinacloudapi.cn. /// @@ -9126,15 +9126,6 @@ internal static string SQL_CannotCreateAuthProvider { } } - /// - /// Looks up a localized string similar to Cannot create normalizer for '{0}'.. - /// - internal static string SQL_CannotCreateNormalizer { - get { - return ResourceManager.GetString("SQL_CannotCreateNormalizer", resourceCulture); - } - } - /// /// Looks up a localized string similar to Cannot find an authentication provider for '{0}'.. /// @@ -9180,6 +9171,15 @@ internal static string SQL_CannotModifyPropertyAsyncOperationInProgress { } } + /// + /// Looks up a localized string similar to Cannot create normalizer for '{0}'.. + /// + internal static string Sql_CanotCreateNormalizer { + get { + return ResourceManager.GetString("Sql_CanotCreateNormalizer", resourceCulture); + } + } + /// /// Looks up a localized string similar to Incorrect authentication parameters specified with certificate authentication.. /// @@ -9639,15 +9639,6 @@ internal static string SQL_InvalidUdt3PartNameFormat { } } - /// - /// Looks up a localized string similar to Cannot use 'Authentication={0}' with 'Password' or 'PWD' connection string keywords.. - /// - internal static string SQL_NonInteractiveWithPassword { - get { - return ResourceManager.GetString("SQL_NonInteractiveWithPassword", resourceCulture); - } - } - /// /// Looks up a localized string similar to The connection does not support MultipleActiveResultSets.. /// @@ -9720,6 +9711,15 @@ internal static string SQL_NonCharColumn { } } + /// + /// Looks up a localized string similar to Cannot use 'Authentication={0}' with 'Password' or 'PWD' connection string keywords.. + /// + internal static string SQL_NonInteractiveWithPassword { + get { + return ResourceManager.GetString("SQL_NonInteractiveWithPassword", resourceCulture); + } + } + /// /// Looks up a localized string similar to SSE Instance re-direction is not supported for non-local user instances.. /// @@ -9819,6 +9819,15 @@ internal static string SQL_ParameterCannotBeEmpty { } } + /// + /// Looks up a localized string similar to Parameter '{0}' cannot have Direction Output or InputOutput when EnableOptimizedParameterBinding is enabled on the parent command.. + /// + internal static string SQL_ParameterDirectionInvalidForOptimizedBinding { + get { + return ResourceManager.GetString("SQL_ParameterDirectionInvalidForOptimizedBinding", resourceCulture); + } + } + /// /// Looks up a localized string similar to Parameter '{0}' exceeds the size limit for the sql_variant datatype.. /// @@ -12077,12 +12086,6 @@ internal static string TCE_DbConnectionString_AttestationProtocol { return ResourceManager.GetString("TCE_DbConnectionString_AttestationProtocol", resourceCulture); } } - - /// - /// Looks up a localized string similar to Specifies an IP address preference when connecting to SQL instances. - /// - internal static string TCE_DbConnectionString_IPAddressPreference - => ResourceManager.GetString("TCE_DbConnectionString_IPAddressPreference", resourceCulture); /// /// Looks up a localized string similar to Default column encryption setting for all the commands on the connection.. @@ -12102,6 +12105,15 @@ internal static string TCE_DbConnectionString_EnclaveAttestationUrl { } } + /// + /// Looks up a localized string similar to Specifies an IP address preference when connecting to SQL instances.. + /// + internal static string TCE_DbConnectionString_IPAddressPreference { + get { + return ResourceManager.GetString("TCE_DbConnectionString_IPAddressPreference", resourceCulture); + } + } + /// /// Looks up a localized string similar to Decryption failed. The last 10 bytes of the encrypted column encryption key are: '{0}'. The first 10 bytes of ciphertext are: '{1}'.. /// diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.resx b/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.resx index c0ac110600..af56ffe4b3 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.resx +++ b/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.resx @@ -4614,4 +4614,7 @@ Non-negative number required. - + + Parameter '{0}' cannot have Direction Output or InputOutput when EnableOptimizedParameterBinding is enabled on the parent command. + + \ No newline at end of file From 92961b116cb8bf6c9e00ab80ce5f1614df54bce3 Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Wed, 23 Jun 2021 21:48:46 +0100 Subject: [PATCH 14/18] add SqlCommnand documentation --- .../Microsoft.Data.SqlClient/SqlCommand.xml | 68 +++++++++++++++---- 1 file changed, 54 insertions(+), 14 deletions(-) diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml index 0738039d4a..9122c52134 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml @@ -286,8 +286,13 @@ The following console application creates updates data within the **AdventureWor The - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - + closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). + + - or - + + + is set to true and a parameter with direction Output or InputOutput has been added to the Parameters collection. + An error occurred in a @@ -399,8 +404,13 @@ To set up this example, create a new Windows application. Put a The - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - + closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). + + - or - + + + is set to true and a parameter with direction Output or InputOutput has been added to the Parameters collection. + @@ -477,8 +487,13 @@ The following console application starts the process of retrieving a data reader The - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - + closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). + + - or - + + + is set to true and a parameter with direction Output or InputOutput has been added to the Parameters collection. + An error occurred in a @@ -584,8 +599,13 @@ This example also passes the `CommandBehavior.CloseConnection` and `CommandBehav The - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - + closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). + + - or - + + + is set to true and a parameter with direction Output or InputOutput has been added to the Parameters collection. + An error occurred in a @@ -702,8 +722,13 @@ To set up this example, create a new Windows application. Put a The - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - + closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). + + - or - + + + is set to true and a parameter with direction Output or InputOutput has been added to the Parameters collection. + An error occurred in a @@ -831,8 +856,13 @@ This example passes the `CommandBehavior.CloseConnection` value in the `behavior The - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - + closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). + + - or - + + + is set to true and a parameter with direction Output or InputOutput has been added to the Parameters collection. + An error occurred in a @@ -940,6 +970,11 @@ The following console application starts the process of retrieving XML data asyn The closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). + + - or - + + + is set to true and a parameter with direction Output or InputOutput has been added to the Parameters collection. An error occurred in a @@ -1067,8 +1102,13 @@ To set up this example, create a new Windows application. Put a The - closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). - + closed or dropped during a streaming operation. For more information about streaming, see [SqlClient Streaming Support](/sql/connect/ado-net/sqlclient-streaming-support). + + - or - + + + is set to true and a parameter with direction Output or InputOutput has been added to the Parameters collection. + An error occurred in a From a1302d0346b382dd582e3076012697e2eb00c02d Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Wed, 23 Jun 2021 22:00:00 +0100 Subject: [PATCH 15/18] fix normalizer resource again --- .../netfx/src/Resources/Strings.Designer.cs | 18 +++++++++--------- .../netfx/src/Resources/Strings.resx | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.Designer.cs b/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.Designer.cs index 69a84e09c8..7289e36f6b 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.Designer.cs +++ b/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.Designer.cs @@ -9126,6 +9126,15 @@ internal static string SQL_CannotCreateAuthProvider { } } + /// + /// Looks up a localized string similar to Cannot create normalizer for '{0}'.. + /// + internal static string SQL_CannotCreateNormalizer { + get { + return ResourceManager.GetString("SQL_CannotCreateNormalizer", resourceCulture); + } + } + /// /// Looks up a localized string similar to Cannot find an authentication provider for '{0}'.. /// @@ -9171,15 +9180,6 @@ internal static string SQL_CannotModifyPropertyAsyncOperationInProgress { } } - /// - /// Looks up a localized string similar to Cannot create normalizer for '{0}'.. - /// - internal static string Sql_CanotCreateNormalizer { - get { - return ResourceManager.GetString("Sql_CanotCreateNormalizer", resourceCulture); - } - } - /// /// Looks up a localized string similar to Incorrect authentication parameters specified with certificate authentication.. /// diff --git a/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.resx b/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.resx index af56ffe4b3..5246f97349 100644 --- a/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.resx +++ b/src/Microsoft.Data.SqlClient/netfx/src/Resources/Strings.resx @@ -3048,7 +3048,7 @@ Subclass did not override a required method. - + Cannot create normalizer for '{0}'. From 3a01525461d69509d64a949d0ef4e5cb5389ffaa Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Wed, 23 Jun 2021 22:37:28 +0100 Subject: [PATCH 16/18] address feedback --- .../Microsoft.Data.SqlClient/SqlCommand.xml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml b/doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml index 9122c52134..62ae7811a8 100644 --- a/doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml +++ b/doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml @@ -291,7 +291,7 @@ The following console application creates updates data within the **AdventureWor - or - - is set to true and a parameter with direction Output or InputOutput has been added to the Parameters collection. + is set to true and a parameter with direction Output or InputOutput has been added to the collection. An error occurred in a @@ -409,7 +409,7 @@ To set up this example, create a new Windows application. Put a - is set to true and a parameter with direction Output or InputOutput has been added to the Parameters collection. + is set to true and a parameter with direction Output or InputOutput has been added to the collection. @@ -492,7 +492,7 @@ The following console application starts the process of retrieving a data reader - or - - is set to true and a parameter with direction Output or InputOutput has been added to the Parameters collection. + is set to true and a parameter with direction Output or InputOutput has been added to the collection. An error occurred in a @@ -604,7 +604,7 @@ This example also passes the `CommandBehavior.CloseConnection` and `CommandBehav - or - - is set to true and a parameter with direction Output or InputOutput has been added to the Parameters collection. + is set to true and a parameter with direction Output or InputOutput has been added to the collection. An error occurred in a @@ -727,7 +727,7 @@ To set up this example, create a new Windows application. Put a - is set to true and a parameter with direction Output or InputOutput has been added to the Parameters collection. + is set to true and a parameter with direction Output or InputOutput has been added to the collection. An error occurred in a @@ -861,7 +861,7 @@ This example passes the `CommandBehavior.CloseConnection` value in the `behavior - or - - is set to true and a parameter with direction Output or InputOutput has been added to the Parameters collection. + is set to true and a parameter with direction Output or InputOutput has been added to the collection. An error occurred in a @@ -974,7 +974,7 @@ The following console application starts the process of retrieving XML data asyn - or - - is set to true and a parameter with direction Output or InputOutput has been added to the Parameters collection. + is set to true and a parameter with direction Output or InputOutput has been added to the collection. An error occurred in a @@ -1107,7 +1107,7 @@ To set up this example, create a new Windows application. Put a - is set to true and a parameter with direction Output or InputOutput has been added to the Parameters collection. + is set to true and a parameter with direction Output or InputOutput has been added to the collection. An error occurred in a From 2b5e8c968cdf40f94f29cffb69f6107e252565c5 Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Thu, 24 Jun 2021 01:30:51 +0100 Subject: [PATCH 17/18] use conditinoal fact in tests --- .../SQL/ParameterTest/ParametersTest.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs index a856aeb8aa..e57b9040e8 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs @@ -532,7 +532,7 @@ private static void ExecuteNonQueryCommand(string connectionString, string cmdTe } } - [Fact] + [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] private static void EnableOptimizedParameterBinding_ParametersAreUsedByName() { int firstInput = 1; @@ -562,7 +562,7 @@ private static void EnableOptimizedParameterBinding_ParametersAreUsedByName() } } - [Fact] + [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] private static void EnableOptimizedParameterBinding_NamesMustMatch() { using (var connection = new SqlConnection(DataTestUtility.TCPConnectionString)) @@ -592,7 +592,7 @@ private static void EnableOptimizedParameterBinding_NamesMustMatch() } } - [Fact] + [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] private static void EnableOptimizedParameterBinding_AllNamesMustBeDeclared() { using (var connection = new SqlConnection(DataTestUtility.TCPConnectionString)) @@ -621,7 +621,7 @@ private static void EnableOptimizedParameterBinding_AllNamesMustBeDeclared() } } - [Fact] + [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] private static void EnableOptimizedParameterBinding_NamesCanBeReUsed() { int firstInput = 1; @@ -655,7 +655,7 @@ private static void EnableOptimizedParameterBinding_NamesCanBeReUsed() } } - [Fact] + [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] private static void EnableOptimizedParameterBinding_InputOutputFails() { int firstInput = 1; @@ -681,7 +681,7 @@ private static void EnableOptimizedParameterBinding_InputOutputFails() } } - [Fact] + [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] private static void EnableOptimizedParameterBinding_OutputFails() { int firstInput = 1; @@ -707,7 +707,7 @@ private static void EnableOptimizedParameterBinding_OutputFails() } } - [Fact] + [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup))] private static void EnableOptimizedParameterBinding_ReturnSucceeds() { int firstInput = 12; From 421ee2159e09635c307660e1d8d7f98f1f24f690 Mon Sep 17 00:00:00 2001 From: Wraith2 Date: Tue, 6 Jul 2021 00:36:31 +0100 Subject: [PATCH 18/18] address feedback --- .../tests/ManualTests/SQL/ParameterTest/ParametersTest.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs index e57b9040e8..3c55b079e5 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/ParametersTest.cs @@ -557,7 +557,6 @@ private static void EnableOptimizedParameterBinding_ParametersAreUsedByName() Assert.Equal(firstInput, secondOutput); Assert.Equal(secondInput, firstOutput); } - } } } @@ -587,7 +586,6 @@ private static void EnableOptimizedParameterBinding_NamesMustMatch() Assert.NotNull(sqlException); Assert.Contains("Must declare the scalar variable",sqlException.Message); Assert.Contains("@DoesNotExist", sqlException.Message); - } } }