Skip to content

Commit

Permalink
Fixes corrupted connection issue when an exception occurs during RPC …
Browse files Browse the repository at this point in the history
…execution with TVP types (#1068)
  • Loading branch information
cheenamalhotra authored May 17, 2021
1 parent ca4957c commit 00d45e8
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 15 deletions.
2 changes: 1 addition & 1 deletion build.proj
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
<FunctionalTests Include="**/tools/Microsoft.DotNet.XUnitExtensions/Microsoft.DotNet.XUnitExtensions.csproj" />
<FunctionalTests Include="**/tools/CoreFx.Private.TestUtilities/CoreFx.Private.TestUtilities.csproj" />
<FunctionalTests Include="**/ManualTests/SQL/UdtTest/UDTs/Address/Address.csproj" />
<FunctionalTests Include="**/Microsoft.Data.SqlClient.Tests.csproj" />
<FunctionalTests Include="**/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj" />

<ManualTests Condition="$(ReferenceType.Contains('NetStandard'))" Include="**/NSLibrary/Microsoft.Data.SqlClient.NSLibrary.csproj" />
<ManualTests Include="**/ManualTests/SQL/UdtTest/UDTs/Address/Address.csproj" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9110,13 +9110,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo
}
catch (Exception e)
{
if (!ADP.IsCatchableExceptionType(e))
{
throw;
}

FailureCleanup(stateObj, e);

throw;
}
FinalizeExecuteRPC(stateObj);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10449,14 +10449,7 @@ internal Task TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, int timeout, boo
}
catch (Exception e)
{
// UNDONE - should not be catching all exceptions!!!
if (!ADP.IsCatchableExceptionType(e))
{
throw;
}

FailureCleanup(stateObj, e);

throw;
}
FinalizeExecuteRPC(stateObj);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using System.Transactions;
using Microsoft.Data.SqlClient.Server;
using Xunit;
using System.Linq;

namespace Microsoft.Data.SqlClient.ManualTesting.Tests
{
Expand Down Expand Up @@ -82,6 +83,99 @@ public void TestPacketNumberWraparound()
Assert.True(enumerator.MaxCount == enumerator.Count);
}

[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureServer))]
public void TestConnectionIsSafeToReuse()
{
using SqlConnection connection = new(DataTestUtility.TCPConnectionString);

// Bad Scenario - exception expected.
try
{
List<Item> list = new()
{
new Item(0),
null,
new Item(2),
new Item(3),
new Item(4),
new Item(5)
};

IEnumerable<int> Ids = list.Select(x => x.id.Value).Distinct();

var sqlParam = new SqlParameter("ids", SqlDbType.Structured)
{
TypeName = "dbo.TableOfIntId",
SqlValue = Ids.Select(x =>
{
SqlDataRecord rec = new(new[] { new SqlMetaData("Id", SqlDbType.Int) });
rec.SetInt32(0, x);
return rec;
})
};

var parameters = new List<SqlParameter>() { sqlParam };
const string SQL = @"SELECT * FROM information_schema.COLUMNS cols INNER JOIN @ids Ids on Ids.id = cols.ORDINAL_POSITION";
using SqlCommand cmd = new(SQL, connection);
cmd.CommandTimeout = 100;
AddCommandParameters(cmd, parameters);
new SqlDataAdapter(cmd).Fill(new("BadFunc"));
Assert.False(true, "Expected exception did not occur");
}
catch (Exception e)
{
// Ignore this exception as it's deliberately introduced.
Assert.True(e.Message.Contains("Object reference not set to an instance of an object"), "Expected exception did not occur");
}

// Good Scenario - No failure expected.
try
{
const string SQL = @"SELECT * FROM information_schema.tables WHERE TABLE_NAME = @TableName";
var parameters = new List<SqlParameter>() { new SqlParameter("@TableName", "Temp") };
using SqlCommand cmd = new(SQL, connection);
cmd.CommandTimeout = 100;
AddCommandParameters(cmd, parameters);
new SqlDataAdapter(cmd).Fill(new("GoodFunc"));
}
catch (Exception e)
{
Assert.False(true, $"Unexpected error occurred: {e.Message}");
}
}

private class Item
{
public Item(int? v)
{
id = v;
}
public int? id { get; set; }
}

static internal void AddCommandParameters(SqlCommand command, IEnumerable parameters)
{
if (parameters == null)
return;

foreach (SqlParameter p in parameters)
{
if (p == null)
continue;

if (p.Value == null)
{
var clone = (SqlParameter)((ICloneable)p).Clone();
clone.Value = DBNull.Value;
command.Parameters.Add(clone);
}
else
{
command.Parameters.Add(p);
}
}
}

public TvpTest()
{
_connStr = DataTestUtility.TCPConnectionString;
Expand Down Expand Up @@ -693,7 +787,7 @@ private bool AllowableDifference(byte[] source, object result, StePermutation me
// allowable max-length adjustments
if (maxLength == resultBytes.Length)
{ // a bit optimistic, but what the heck.
// truncation
// truncation
if (maxLength <= source.Length)
{
returnValue = true;
Expand Down

0 comments on commit 00d45e8

Please sign in to comment.