我正在使用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);
}
}
}
我知道我可以(并且有)试验有足够的超时/批量大小参数。但我的问题是,从编码的角度来看,有没有办法确定哪个数据库服务器是给我带来问题的呢?
由于
答案 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。