Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix retry with SqlDataAdapter.Fill(SqlDataTable) on .NET Framework #2084

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2409,8 +2409,8 @@ public IAsyncResult BeginExecuteReader(AsyncCallback callback, object stateObjec
/// <include file='../../../../../../../doc/snippets/Microsoft.Data.SqlClient/SqlCommand.xml' path='docs/members[@name="SqlCommand"]/ExecuteDbDataReader[@name="CommandBehavior"]/*'/>
protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior)
{
SqlClientEventSource.Log.TryCorrelationTraceEvent("<sc.SqlCommand.ExecuteDbDataReader|API|Correlation> ObjectID {0}, ActivityID {1}", ObjectID, ActivityCorrelator.Current);
return ExecuteReader(behavior, nameof(ExecuteReader));
SqlClientEventSource.Log.TryCorrelationTraceEvent("<sc.SqlCommand.ExecuteDbDataReader|API|Correlation> ObjectID {0}, ActivityID {1}, Client Connection Id {2}, Command Text '{3}'", ObjectID, ActivityCorrelator.Current, Connection?.ClientConnectionId, CommandText);
return ExecuteReader(behavior);
}

private SqlDataReader ExecuteReaderWithRetry(CommandBehavior behavior, string method)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,22 +68,90 @@ public AdapterTest()
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))]
public void SimpleFillTest()
{
using (SqlConnection conn = new SqlConnection(DataTestUtility.TCPConnectionString))
using (SqlDataAdapter adapter = new SqlDataAdapter("SELECT EmployeeID, LastName, FirstName, Title, Address, City, Region, PostalCode, Country FROM Employees", conn))
using SqlConnection conn = new(DataTestUtility.TCPConnectionString);
using SqlDataAdapter adapter = new("SELECT EmployeeID, LastName, FirstName, Title, Address, City, Region, PostalCode, Country FROM Employees", conn);

DataSet employeesSet = new();
DataTestUtility.AssertEqualsWithDescription(0, employeesSet.Tables.Count, "Unexpected tables count before fill.");
adapter.Fill(employeesSet, "Employees");

DataTestUtility.AssertEqualsWithDescription(1, employeesSet.Tables.Count, "Unexpected tables count after fill.");
DataTestUtility.AssertEqualsWithDescription("Employees", employeesSet.Tables[0].TableName, "Unexpected table name.");

DataTestUtility.AssertEqualsWithDescription(9, employeesSet.Tables["Employees"].Columns.Count, "Unexpected columns count.");
employeesSet.Tables["Employees"].Columns.Remove("LastName");
employeesSet.Tables["Employees"].Columns.Remove("FirstName");
employeesSet.Tables["Employees"].Columns.Remove("Title");
DataTestUtility.AssertEqualsWithDescription(6, employeesSet.Tables["Employees"].Columns.Count, "Unexpected columns count after column removal.");

DataSet dataSet = new();
adapter.Fill(dataSet);
DataTestUtility.AssertEqualsWithDescription(1, dataSet.Tables.Count, "Unexpected tables count after fill.");
DataTestUtility.AssertEqualsWithDescription(9, dataSet.Tables[0].Columns.Count, "Unexpected column after fill.");

DataSet dataSet2 = new();
adapter.Fill(dataSet2, 0, 2, "Employees");
DataTestUtility.AssertEqualsWithDescription(1, dataSet2.Tables.Count, "Unexpected tables count after fill.");
DataTestUtility.AssertEqualsWithDescription(2, dataSet2.Tables[0].Rows.Count, "Unexpected row count after fill.");
DataTestUtility.AssertEqualsWithDescription(9, dataSet2.Tables[0].Columns.Count, "Unexpected column after fill.");

DataTable table = new();
adapter.Fill(table);
DataTestUtility.AssertEqualsWithDescription(9, table.Columns.Count, "Unexpected columns count.");

DataTable table2 = new();
adapter.Fill(0, 2, table2);
DataTestUtility.AssertEqualsWithDescription(9, table2.Columns.Count, "Unexpected columns count.");
DataTestUtility.AssertEqualsWithDescription(2, table2.Rows.Count, "Unexpected rows count.");
}

// TODO Synapse: Remove Northwind dependency by creating required tables in setup.
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))]
public void FillShouldAllowRetryLogicProviderToBeInvoked()
{
int maxRetries = 3;
int expectedAttempts = maxRetries - 1;
int retryCount = 0;

SqlRetryLogicOption options = new()
{
DataSet employeesSet = new DataSet();
DataTestUtility.AssertEqualsWithDescription(0, employeesSet.Tables.Count, "Unexpected tables count before fill.");
adapter.Fill(employeesSet, "Employees");

DataTestUtility.AssertEqualsWithDescription(1, employeesSet.Tables.Count, "Unexpected tables count after fill.");
DataTestUtility.AssertEqualsWithDescription("Employees", employeesSet.Tables[0].TableName, "Unexpected table name.");

DataTestUtility.AssertEqualsWithDescription(9, employeesSet.Tables["Employees"].Columns.Count, "Unexpected columns count.");
employeesSet.Tables["Employees"].Columns.Remove("LastName");
employeesSet.Tables["Employees"].Columns.Remove("FirstName");
employeesSet.Tables["Employees"].Columns.Remove("Title");
DataTestUtility.AssertEqualsWithDescription(6, employeesSet.Tables["Employees"].Columns.Count, "Unexpected columns count after column removal.");
}
NumberOfTries = maxRetries,
DeltaTime = TimeSpan.FromMilliseconds(100),
MaxTimeInterval = TimeSpan.FromMilliseconds(500),
TransientErrors = new int[] { 26, 4060, 233, -1, 17142, -2, 2812 }
};
SqlRetryLogicBaseProvider provider = SqlConfigurableRetryFactory.CreateFixedRetryProvider(options);

string query = "WAITFOR DELAY '00:00:02';SELECT 1";
SqlConnectionStringBuilder builder = new(DataTestUtility.TCPConnectionString)
{
ConnectTimeout = 1
};

using var connection = new SqlConnection(builder.ConnectionString);
using SqlCommand command = new(query, connection);
command.CommandTimeout = 1;
command.RetryLogicProvider = provider;
command.RetryLogicProvider.Retrying += (object sender, SqlRetryingEventArgs e) =>
{
retryCount = e.RetryCount;
Assert.Equal(e.RetryCount, e.Exceptions.Count);
Assert.NotEqual(TimeSpan.Zero, e.Delay);
};

connection.Open();

AggregateException exception = Assert.Throws<AggregateException>(() =>
{
DataTable dt = new();
using (SqlDataAdapter adapter = new(command))
{
adapter.Fill(dt);
}
});

Assert.Contains($"The number of retries has exceeded the maximum of {maxRetries} attempt(s)", exception.Message);
Assert.Equal(expectedAttempts, retryCount);
}

// TODO Synapse: Remove Northwind dependency by creating required tables in setup.
Expand Down