.NET Data Provider for Teradata Asynchronous Operations

Blog
The best minds from Teradata, our partners, and customers blog about whatever takes their fancy.
Teradata Employee

.NET Framework has a very broad support for Asynchronous operations including a well defined Asynchronous Programming Model. All asynchronous operations are started by invoking a Begin method; later a corresponding End method is invoked to retrieve the result. .NET Application can use three different techniques to rendezvous with the asynchronous operation: a) Callback Method b) Poll for status and c) Wait on a thread synchronization handle. For Example FileStream class has BeginRead/EndRead methods and delegates have BeginInvoke/EndInvoke methods. For additional information about Asynchronous Programming and Patterns refer to:

MSDN: Asynchronous Programming Design Patterns

ADO.NET 2.0 specification defines three methods to execute SQL queries: 

  • ExecuteReader: returns result sets with one or more rows.
  • ExecuteScalar: result in a scalar value like Int32.
  • ExecuteNonQuery: returns number of rows affected.

These methods are part of DbCommand class in System.Data.Common namespace. These methods are synchronous; that is the executing thread is I/O bound because it is waiting for a response from Teradata database. Unfortunately DbCommand does not define Asynchronous Execution methods. However applications can call these synchronous methods asynchronously using a delegate. Code snippet below shows how to invoke ExecuteNonQuery asynchronously:

internal class AsyncCommand
{
private delegate Int32 AsyncExecuteNonQuery();

public AsyncCommand(String connectionString)
{
_asyncExecuteNonQuery = new AsyncExecuteNonQuery(_command.ExecuteNonQuery);
}

public void AsyncExecuteCommand(String sqlText)
{
_command.CommandText = sqlText;
_asyncResult = _asyncExecuteNonQuery.BeginInvoke(null, null);
}

public Nullable<Int32> AffectedRows
{
get
{
if (_asyncResult != null)
{
Int32 result = _asyncExecuteNonQuery.EndInvoke(_asyncResult);
}
else
{
return null;
}
}
}
}

The AsyncExecuteNonQuery.BeginInvoke method shown above will dispatch a thread-pool thread to execute the DbCommand.ExecuteNonQuery method. In other words, the task identified by the delegate, in this case ExecuteNonQuery, is performed by another thread synchronously. For example an application executing 10 commands across 10 connections will result in 10 threads. The Performance Monitor graph below shows that number of available worker threads in the thread-pool decrease as each DbCommand.ExecuteNonQuery is invoked through a delegate. Later the threads are returned to the pool.

This graph must raise some alarms. That is applications servers will have scalability issues as the number of connections and users increase overtime.

See MSDN: Asynchronous Programming Using Delegates for additional information about calling Synchronous methods asynchronously.

.NET Data Provider for Teradata solves this scalability issue by introducing 4 new methods for asynchronous operations corresponding to two of the three Execute methods described above. The application's thread of execution is never I/O bound and .NET Data Provider for Teradata does not use one thread for each SQL Command. The code snippet below shows how to take advantage of TdCommand class Asynchronous methods:

internal class AsyncTdCommand
{
public AsyncTdCommand(String connectionString)
{
}

public void AsyncExecuteCommand(String sqlText)
{
_command.CommandText = sqlText;
_asyncResult = _command.BeginExecuteNonQuery();
}

public Nullable<Int32> AffectedRows
{
get
{
if (_asyncResult != null)
{
Int32 result = _command.EndExecuteNonQuery(_asyncResult);
}
else
{
return null;
}
}
}
}

TdCommand class asynchronous methods are highly scalable. For example an application executing 10 commands across 10 connections will only utilize one I/O thread for very short amount time . The Performance Monitor graph below shows that the number of available worker threads never decrease and one I/O thread is used for very short amount time.

In summary there are lots of scenarios where the Asynchronous feature of the .NET Data Provider for Teradata is very beneficial. For example

  • Use it in ASP.NET Asynchronous Pages to create very highly scalable applications.
  • Use it to execute two or more SQL commands simultaneously across two or more connections. There are scenarios where a multi-statement requests cannot be used; for example when one SQL command executes in half the time.
  •  Use it to execute background database commands in Windows Forms applications.