SqlBulkCopy.WriteToServer () 계속 "연결이 닫혔습니다."

c# sqlbulkcopy sql-server

문제

이것은 나에게 이해가되지 않지만 어쩌면 날카로운 눈을 가진 사람이 문제를 발견 할 수 있습니다.

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);
                }
            });
    }
}

당신이 물어볼 경우를 대비해 몇 가지 메모 :

  • ObjectReader는 FastMember IDataReader 구현입니다. 빠르고 빨리. 이 파일은 나열된 속성을 사용하여 사용자 지정 개체로 파일을 읽습니다.
  • 모든 단일 파일에 대해 오류가 발생합니다.
  • 다시 말하지만, 이것은 내 컴퓨터에서 서비스 및 콘솔 앱으로 모두 작동합니다. 심지어 서버에서 한 번 작동하도록했습니다. 그것은 오류를 던졌고 결코 다시 일하지 않았습니다.

어떤 아이디어?

수락 된 답변

비동기 문제 인 것 같습니다.

제가 틀렸다면 알려주세요. 그러나 주목할 것은 SqlBulkCopyObjectReader 를 using 문에 사용하는 것입니다. 그러나 모든 처리를 비동기 적으로 수행하고 있습니다. 일단 호출하고 작업을 시작 using 문은 객체를 삭제하므로 연결이 끊어집니다.

이상한 점은 때때로 작동하는 것처럼 들리지만 어쩌면 그 시점에서 경쟁 조건이 될 수 있습니다.


인기 답변

이것은 SqlBulkCopy 구현의 버그로 보입니다. 대량의 대량 복사를 동시에 다른 작업에서 병렬로 실행하고 네트워크 연결을 해제 한 다음 전체 가비지 수집을 트리거하면 GC의 finalizer 스레드에서이 예외가 안정적으로 발생합니다. 그것은 완전히 피할 수없는 것입니다.

WriteToServerAsync 작업을 계속하고 오류를 처리하기 때문에 발생하지 않아야합니다. 그러나 구현에서는 오류가 발생해도 계속 또는 기다리지 않는 새로운 작업을 시작합니다.

이것은 여전히 ​​.NET 4.6.2의 버그 인 것 같습니다.

내가 볼 수있는 유일한 수정 사항은 TaskScheduler.UnobservedTaskException 을 구독하고 문제를 식별하는 무언가를 스택 TaskScheduler.UnobservedTaskException 에서 찾습니다. 그건 그렇고 픽스가 아니라 해킹입니다.



아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.