这对我来说毫无意义,但也许有眼睛敏锐的人可以发现问题。
我有一个使用FileSystemWatcher的Windows服务。它处理一些文件并将数据上传到MSSQL数据库。它在我的机器上完全正常工作 - 与Visual Studio分离(即不调试)并作为服务运行。如果将这个已编译的代码复制到我们的服务器,并让它指向同一个数据库,甚至是相同的文件(!),我每次都会收到此错误:
System.InvalidOperationException: Invalid operation. The connection is closed.
at System.Data.SqlClient.SqlConnection.GetOpenTdsConnection()
at System.Data.SqlClient.SqlBulkCopy.CopyBatchesAsyncContinuedOnError(Boolean cleanupParser)
at System.Data.SqlClient.SqlBulkCopy.<>c__DisplayClass30.<CopyBatchesAsyncContinuedOnSuccess>b__2c()
at System.Data.SqlClient.AsyncHelper.<>c__DisplayClass9.<ContinueTask>b__8(Task tsk)
我已尝试将本地代码指向服务器的文件,但它运行正常。 .Net 4.5.1在两台机器上。服务都在同一个域用户下运行。令人费解。也许我对SqlBulkCopy.WriteToServerAsync()有些不了解的东西?它会自动共享连接吗?它是否在通话之间关闭?这是相关的代码:
private static void ProcessFile(FileInfo fileInfo)
{
using (var bulkCopy = new SqlBulkCopy("Data Source=myserver;Initial Catalog=mydb;Persist Security Info=True;User ID=myusr;Password=mypwd;")
using (var objRdr = ObjectReader.Create(ReadLogFile(fileInfo)
.Where(x => !string.IsNullOrEmpty(x.Level)),
"Id", "AppId", "AppDomain", "AppMachine",
"LocalDate", "UtcDate", "Thread", "Level", "Logger", "Usrname",
"ClassName", "MethodName", "LineNo", "Message", "Exception",
"StackTrace", "Properties"))
{
bulkCopy.DestinationTableName = "EventLog";
bulkCopy.BulkCopyTimeout = 600;
bulkCopy.EnableStreaming = true;
bulkCopy.BatchSize = AppConfig.WriteBatchSize;
bulkCopy.WriteToServerAsync(objRdr).ContinueWith(t =>
{
if (t.Status == TaskStatus.Faulted)
{
CopyToFailedDirectory(fileInfo);
_log.Error(
string.Format(
"Error copying logs to database for file {0}. File has been copied to failed directory for inspection.",
fileInfo.FullName), t.Exception.InnerException ?? t.Exception);
Debug.WriteLine("new handle error {0}",
(t.Exception.InnerException ?? t.Exception).Message);
}
if (t.Status == TaskStatus.RanToCompletion)
{
_log.InfoFormat("File {0} logs have been copied to database.", fileInfo.FullName);
Debug.WriteLine("Yay, finished {0}!", fileInfo.Name);
}
// if this is the last one, delete the original file
if (t.Status == TaskStatus.Faulted || t.Status == TaskStatus.RanToCompletion)
{
Debug.WriteLine("deleting file {0}", fileInfo.Name);
PurgeFile(fileInfo);
}
});
}
}
如果你问的话,请记下一些笔记:
有什么想法吗?
答案 0 :(得分:5)
看起来像是异步的问题。
如果我错了,请告诉我,但我注意到您在使用声明中使用了SqlBulkCopy
和ObjectReader
这很好,但是,您正在异步进行所有处理。一旦你调用它并开始工作,你的using
语句就会处理你的对象,这也会破坏你的连接。
奇怪的是,它听起来有时会起作用,但也许它只是在那时成为一种竞争条件。
答案 1 :(得分:0)
这让我觉得它是SqlBulkCopy实现中的一个错误。如果同时在单独的任务中并行运行(大量)批量副本,禁用网络连接然后触发完整的垃圾回收,您将可靠地在GC的终结器线程上抛出此异常。这是完全不可避免的。
这不应该发生,因为您继续执行$('#selectChannel').val(data.channel);
$('#fromDate').val(data.fromDate);
任务并处理故障。但是在实施过程中,出错时他们会开始一项新的任务,他们不会继续或等待。
这似乎仍然是.NET 4.6.2中的一个错误。
我能看到的唯一解决方案是订阅WriteToServerAsync
并在stacktrace中查找标识问题的内容。顺便说一句,这不是一个修复,它是一个黑客。
答案 2 :(得分:0)
晚点把这个扔到这里,但是我当时认为SqlBulkCopy是同样的问题。尝试了其他答案中的某些步骤,但是没有运气。在我的情况下,结果表明实际错误是由于数据中的字符串超出了varchar列之一的最大长度而引起的,但是由于某种原因,我遇到的唯一错误是有关关闭连接的错误。
奇怪的是,我的同事尝试了同样的事情,并收到有关varchar超出范围的实际错误消息。因此,我们修复了数据,一切正常,但是如果由于这个错误而您在这里,而其他任何事情都没有,那么您可能要开始在数据中寻找其他问题。