SqlBulkCopy - 哪个数据库导致异常?

时间:2014-01-17 12:40:40

标签: c# mysql sql-server ado.net

我正在使用SqlBulkCopy将一批记录从MySQL复制到SQL Server。

在30秒之后,我得到了这个

System.Data.SqlClient.SqlException (0x80131904): Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.
The statement has been terminated.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
   at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
   at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async)
   at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe)
   at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()

异常中有一个'错误'对象,其中包含以下详细信息:

Message: Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.
LineNumber: 0
Source: .Net SqlClient Data Provider
Procedure: 
Index #1
Message: The statement has been terminated.
LineNumber: 1
Source: .Net SqlClient Data Provider
Procedure: 

这是代码

using (MySqlConnection sourceConnection = new MySqlConnection(AccManConnectionString)) {
sourceConnection.Open();
MySqlCommand commandSourceData = new MySqlCommand(string.Format(sql, VersionNum.ToString()), sourceConnection);
for (int i = 0; i < ParamNames.Length; i++)
{
    commandSourceData.Parameters.AddWithValue(ParamNames[i], SetIDList[i]);
}
MySqlDataReader reader = commandSourceData.ExecuteReader();
using (SqlConnection destinationConnection = new SqlConnection(TimetableConnectionString))
{
    try
    {
    destinationConnection.Open();   
    using (SqlBulkCopy bulkCopy = new SqlBulkCopy(destinationConnection))
    {
        bulkCopy.DestinationTableName = "NetworkID";

        // Configure the batch sizes and timeouts (cofig code omitted)
        bulkCopy.BatchSize = batchSize;
            bulkCopy.BulkCopyTimeout = timeout;

        try
        {
        bulkCopy.WriteToServer(reader);
        SqlCommand update = new SqlCommand(string.Format("UPDATE p SET p.Username = n.Username FROM NetworkID n INNER JOIN Person p ON n.PersonID = p.PersonID and n.VersionID = {0} where p.VersionID = {0}", VersionNum), destinationConnection);
        update.ExecuteNonQuery();
        }
        catch (SqlException ex)
        {
        log.Error("Exception caught", ex);
        }
        finally
        {
        reader.Close();
        }
    }
    }
    catch (Exception e)
    {
    log.Error("Exception caught", e);
    }
 }
}

我知道我可以(并且有)试验有足够的超时/批量大小参数。但我的问题是,从编码的角度来看,有没有办法确定哪个数据库服务器是给我带来问题的呢?

由于

1 个答案:

答案 0 :(得分:1)

您遇到的超时可能会受到设置SqlBulkCopy.BulkCopyTimeOut的影响,默认值为30秒。

至于确定问题所在,最好的办法是抓住SqlException以查看它是否包含更多细节,但在您的实例中我相信这将是您的代码(客户端)超时。

SqlException上的文档提供了一个很好的示例,说明如何枚举异常中包含的错误。

更新1

我可以看到你正在使用MySqlCommand,我猜这是Devart,如果你没有在这个命令上设置超时,那么你需要使用语法CommandTimeout。< / p>

MySqlCommand commandSourceData = new MySqlCommand(string.Format(sql, VersionNum.ToString()), sourceConnection);
commandSourceData.CommandTimeout = timeout;

您还应该在SqlCommand上添加一个。

SqlCommand update = new SqlCommand(string.Format("UPDATE p SET p.Username = n.Username FROM NetworkID n INNER JOIN Person p ON n.PersonID = p.PersonID and n.VersionID = {0} where p.VersionID = {0}", VersionNum), destinationConnection);
update.CommandTimeout = timeout;

更新2

只需阅读SqlBulkCopy上的文档,并注意到以下内容:

  

如果禁用了多个活动结果集(MARS),WriteToServer会生成   连接忙。如果启用了MARS,则可以将呼叫交错到   WriteToServer与其他命令在同一连接中。

我不确定您是否使用MARS,但是,上面的代码调用SQL来在WriteToServer方法之后进行更新,但在关闭BulkCopy之前(通过使用)。您可以尝试通过在Update之前调用close来显式关闭SQLBulkCopy,或者在BulkCopy的Using语句之外移动Update。