diff options
author | Steve Pfister <steveisok@users.noreply.github.com> | 2019-10-31 00:25:25 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-10-31 00:25:25 +0300 |
commit | 6e65509a17da898933705899677c22eae437d68a (patch) | |
tree | 7fa328154fec5bfec6c74faa5fa8e7e090083b68 | |
parent | 49f1c453f75e36948d0386d862378eb0dff51455 (diff) |
Backport SqlCommand Fix
Backport of https://github.com/dotnet/corefx/pull/29614 (#368)
Fixes https://github.com/mono/mono/issues/14450
4 files changed, 120 insertions, 2 deletions
diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlCommand.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlCommand.cs index 40a20092f6..ed356e5ce8 100644 --- a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlCommand.cs +++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlCommand.cs @@ -1145,7 +1145,7 @@ namespace System.Data.SqlClient Task task = null; // only send over SQL Batch command if we are not a stored proc and have no parameters and not in batch RPC mode - if ((System.Data.CommandType.Text == this.CommandType) && (0 == GetParameterCount(_parameters))) + if (!BatchRPCMode && (System.Data.CommandType.Text == this.CommandType) && (0 == GetParameterCount(_parameters))) { Debug.Assert(!sendToPipe, "trying to send non-context command to pipe"); if (null != statistics) @@ -2534,7 +2534,15 @@ namespace System.Data.SqlClient GetStateObject(); Task writeTask = null; - if ((System.Data.CommandType.Text == this.CommandType) && (0 == GetParameterCount(_parameters))) + if (BatchRPCMode) + { + Debug.Assert(inSchema == false, "Batch RPC does not support schema only command beahvior"); + Debug.Assert(!IsPrepared, "Batch RPC should not be prepared!"); + Debug.Assert(!IsDirty, "Batch RPC should not be marked as dirty!"); + Debug.Assert(_SqlRPCBatchArray != null, "RunExecuteReader rpc array not provided"); + writeTask = _stateObj.Parser.TdsExecuteRPC( _SqlRPCBatchArray, timeout, inSchema, this.Notification, _stateObj, CommandType.StoredProcedure == CommandType, sync: !asyncWrite); + } + else if ((System.Data.CommandType.Text == this.CommandType) && (0 == GetParameterCount(_parameters))) { // Send over SQL Batch command if we are not a stored proc and have no parameters Debug.Assert(!IsUserPrepared, "CommandType.Text with no params should not be prepared!"); diff --git a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlParameterHelper.cs b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlParameterHelper.cs index 9431a021f4..7900e0d903 100644 --- a/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlParameterHelper.cs +++ b/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlParameterHelper.cs @@ -231,6 +231,8 @@ namespace System.Data.SqlClient destination._sourceVersion = _sourceVersion; destination._sourceColumnNullMapping = _sourceColumnNullMapping; destination._isNullable = _isNullable; + destination._parameterName = _parameterName; + destination._isNull = _isNull; } } } diff --git a/src/System.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/SqlAdapterUpdateBatch.cs b/src/System.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/SqlAdapterUpdateBatch.cs new file mode 100644 index 0000000000..7f00d180c2 --- /dev/null +++ b/src/System.Data.SqlClient/tests/ManualTests/SQL/ParameterTest/SqlAdapterUpdateBatch.cs @@ -0,0 +1,107 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using Xunit; + +namespace System.Data.SqlClient.ManualTesting.Tests +{ + public class SqlAdapterUpdateBatch + { + [CheckConnStrSetupFact] + public void SqlAdapterTest() + { + string tableName = "BatchDemoTable"; + try + { + var createTableQuery = "IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='BatchDemoTable' AND xtype='U')" + + " CREATE TABLE [dbo].[" + tableName + "]([TransactionNumber][int] IDENTITY(1, 1) NOT NULL,[Level] [nvarchar] (50) NOT NULL," + + "[Message] [nvarchar] (500) NOT NULL,[EventTime] [datetime]NOT NULL,CONSTRAINT[PK_BatchDemoTable] " + + "PRIMARY KEY CLUSTERED([TransactionNumber] ASC)WITH(PAD_INDEX = OFF,STATISTICS_NORECOMPUTE = OFF, " + + "IGNORE_DUP_KEY = OFF,ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON,FILLFACTOR = 90) ON[PRIMARY]) ON[PRIMARY]"; + + using (var connection = new SqlConnection(DataTestUtility.TcpConnStr)) + using (var cmd = new SqlCommand(createTableQuery, connection)) + { + connection.Open(); + cmd.ExecuteNonQuery(); + } + ExecuteNonQueries(); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + Console.WriteLine(ex.StackTrace); + } + finally + { + var dropTableQuery = "DROP TABLE IF EXISTS " + tableName; + using (var connection = new SqlConnection(DataTestUtility.TcpConnStr)) + using (var cmd = new SqlCommand(dropTableQuery, connection)) + { + connection.Open(); + cmd.ExecuteNonQuery(); + } + } + } + + + public class EventInfo + { + public string Level { get; set; } + public string Message { get; set; } + public DateTime EventTime { get; set; } + + public EventInfo() + { + EventTime = DateTime.Now; + } + } + + public static void ExecuteNonQueries() + { + List<EventInfo> entities = new List<EventInfo> + { + new EventInfo {Level = "L1", Message = "Message 1"}, + new EventInfo {Level = "L2", Message = "Message 2"}, + new EventInfo {Level = "L3", Message = "Message 3"}, + new EventInfo {Level = "L4", Message = "Message 4"}, + }; + + var sql = "INSERT INTO BatchDemoTable(Level, Message, EventTime) VALUES(@Level, @Message, @EventTime)"; + using (var connection = new SqlConnection(DataTestUtility.TcpConnStr)) + using (var adapter = new SqlDataAdapter()) + using (var cmd = new SqlCommand(sql, connection)) + { + cmd.Parameters.Add(new SqlParameter("@Level", System.Data.SqlDbType.NVarChar, 50, "Level")); + cmd.Parameters.Add(new SqlParameter("@Message", SqlDbType.NVarChar, 500, "Message")); + cmd.Parameters.Add(new SqlParameter("@EventTime", SqlDbType.DateTime, 0, "EventTime")); + cmd.UpdatedRowSource = UpdateRowSource.None; + + adapter.InsertCommand = cmd; + adapter.UpdateBatchSize = 2; + + adapter.Update(ConvertToTable(entities)); + } + } + private static DataTable ConvertToTable(List<EventInfo> entities) + { + var table = new DataTable(typeof(EventInfo).Name); + + table.Columns.Add("Level", typeof(string)); + table.Columns.Add("Message", typeof(string)); + table.Columns.Add("EventTime", typeof(DateTime)); + + foreach (var entity in entities) + { + var row = table.NewRow(); + row["Level"] = entity.Level; + row["Message"] = entity.Message; + row["EventTime"] = entity.EventTime; + table.Rows.Add(row); + } + return table; + } + } +}
\ No newline at end of file diff --git a/src/System.Data.SqlClient/tests/ManualTests/System.Data.SqlClient.ManualTesting.Tests.csproj b/src/System.Data.SqlClient/tests/ManualTests/System.Data.SqlClient.ManualTesting.Tests.csproj index d0fa8722ac..6475be9fbc 100644 --- a/src/System.Data.SqlClient/tests/ManualTests/System.Data.SqlClient.ManualTesting.Tests.csproj +++ b/src/System.Data.SqlClient/tests/ManualTests/System.Data.SqlClient.ManualTesting.Tests.csproj @@ -33,6 +33,7 @@ <Compile Include="SQL\ParameterTest\DateTimeVariantTest.cs" /> <Compile Include="SQL\ParameterTest\OutputParameter.cs" /> <Compile Include="SQL\ParameterTest\ParametersTest.cs" /> + <Compile Include="SQL\ParameterTest\SqlAdapterUpdateBatch.cs" /> <Compile Include="SQL\ParameterTest\SqlVariantParam.cs" /> <Compile Include="SQL\ParameterTest\SteAttribute.cs" /> <Compile Include="SQL\ParameterTest\SteParam.cs" /> |