Do you really need an app to do this? The most efficient way will be to just execute a SQL statement on the server which transfers the data between the tables.
SqlBulkCopy should be easily fast enough with a single thread. For best performance consider loading the data with a datareader and decorating it (decorator pattern) with a class which does the transformation required. You then pass the decorated IDataReader to the SqlBulkCopy to get a continuous stream of data between tables that will keep memory overhead low and complete the transfer in a matter of seconds.
Example: An input table A with one column of type float, and an output table B with a single column of type float. We will extract all of the numbers from table A and insert the square root of every non-negative number into table B.
class SqrtingDataDecorator : IDataReader
{
private readonly IDataReader _decorated;
private double _input;
public SqrtingDataDecorator(IDataReader decorated)
{
_decorated = decorated;
}
public bool Read()
{
while (_decorated.Read())
{
_input = _decorated.GetDouble(0);
if (_input >= 0)
return true;
}
return false;
}
public object GetValue(int index)
{
return Math.Sqrt(_input);
}
public int FieldCount { get { return 1; } }
//other IDataReader members just throw NotSupportedExceptions,
//return null or do nothing. Omitted for clarity.
}
Here is the bit that does the work
//get the input datareader
IDataReader dr = ///.ExecuteDataReader("select floatCol from A", or whatever
using (SqlTransaction tx = _connection.BeginTransaction())
{
try
{
using (SqlBulkCopy sqlBulkCopy =
new SqlBulkCopy(_connection, SqlBulkCopyOptions.Default, tx))
{
sqlBulkCopy.DestinationTableName = "B";
SetColumnMappings(sqlBulkCopy.ColumnMappings);
//above method omitted for clarity, easy to figure out
//now wrap the input datareader in the decorator
var sqrter = new SqrtingDataDecorator(dr);
//the following line does the data transfer.
sqlBulkCopy.WriteToServer(sqrter);
tx.Commit();
}
}
catch
{
tx.Rollback();
throw;
}
}