[sqlite] System.Data.SQLite Close ()가 데이터베이스 파일을 해제하지 않습니다.

파일을 삭제하기 전에 데이터베이스를 닫는 데 문제가 있습니다. 코드는

 myconnection.Close();
 File.Delete(filename);

그리고 Delete는 파일이 아직 사용 중이라는 예외를 발생시킵니다. 몇 분 후에 디버거에서 Delete ()를 다시 시도 했으므로 타이밍 문제가 아닙니다.

트랜잭션 코드가 있지만 Close () 호출 전에 전혀 실행되지 않습니다. 그래서 나는 그것이 공개 거래가 아니라고 확신합니다. 열기와 닫기 사이의 SQL 명령은 선택 사항입니다.

ProcMon은 데이터베이스 파일을보고있는 프로그램과 바이러스 백신을 보여줍니다. close () 후에 db 파일을 해제하는 프로그램이 표시되지 않습니다.

Visual Studio 2010, C #, System.Data.SQLite 버전 1.0.77.0, Win7

이와 같은 2 년 된 버그를 보았지만 변경 로그에 수정되었다고 표시됩니다.

내가 확인할 수있는 다른 것이 있습니까? 열려있는 명령 또는 트랜잭션 목록을 얻는 방법이 있습니까?


새로운 작동 코드 :

 db.Close();
 GC.Collect();   // yes, really release the db

 bool worked = false;
 int tries = 1;
 while ((tries < 4) && (!worked))
 {
    try
    {
       Thread.Sleep(tries * 100);
       File.Delete(filename);
       worked = true;
    }
    catch (IOException e)   // delete only throws this on locking
    {
       tries++;
    }
 }
 if (!worked)
    throw new IOException("Unable to close file" + filename);



답변

얼마 전 C # 용 DB 추상화 계층을 작성하는 동안 동일한 문제가 발생했으며 실제로 문제가 무엇인지 알아 내지 못했습니다. 내 라이브러리를 사용하여 SQLite DB를 삭제하려고 할 때 예외가 발생했습니다.

어쨌든, 오늘 오후에 나는 모든 것을 다시 살펴 보았고 그것이 왜 단번에 그렇게했는지 알아 내려고 노력할 것이라고 생각했습니다. 그래서 여기에 제가 지금까지 찾은 것이 있습니다.

호출 할 때 발생 SQLiteConnection.Close()하는 일은 SQLiteConnectionHandleSQLite 데이터베이스 인스턴스를 가리키는 여러 검사 및 기타 사항과 함께 삭제 됩니다. 이 작업은에 대한 호출을 통해 수행 SQLiteConnectionHandle.Dispose()되지만 CLR의 가비지 수집기가 일부 가비지 수집을 수행 할 때까지 실제로 포인터를 해제하지 않습니다. 호출 SQLiteConnectionHandleCriticalHandle.ReleaseHandle()함수를 재정의하기 때문에sqlite3_close_interop()(다른 함수를 통해) 데이터베이스를 닫지 않습니다.

내 관점에서 이것은 프로그래머가 데이터베이스가 닫힐 때 실제로 확실하지 않기 때문에 일을 수행하는 매우 나쁜 방법이지만 그것이 수행 된 방식이므로 지금은 함께 살거나 커밋해야한다고 생각합니다. System.Data.SQLite에 대한 몇 가지 변경 사항. 모든 자원 봉사자들은 그렇게 할 수 있습니다. 불행히도 내년 이전에 그렇게 할 시간이 없습니다.

TL; DR
솔루션은를 호출 한 후 SQLiteConnection.Close()및 호출하기 전에 GC를 강제 실행하는 것 File.Delete()입니다.

다음은 샘플 코드입니다.

string filename = "testFile.db";
SQLiteConnection connection = new SQLiteConnection("Data Source=" + filename + ";Version=3;");
connection.Close();
GC.Collect();
GC.WaitForPendingFinalizers();
File.Delete(filename);

행운을 빕니다. 도움이되기를 바랍니다.


답변

그냥 GC.Collect()나를 위해 작동하지 않았다.

파일 삭제를 진행하기 위해 GC.WaitForPendingFinalizers()나중에 추가해야했습니다 GC.Collect().


답변

제 경우에는 SQLiteCommand명시 적으로 삭제하지 않고 객체를 생성 했습니다.

var command = connection.CreateCommand();
command.CommandText = commandText;
value = command.ExecuteScalar();

using명령문에 내 명령을 래핑하고 문제를 해결했습니다.

static public class SqliteExtensions
{
    public static object ExecuteScalar(this SQLiteConnection connection, string commandText)
    {
        using (var command = connection.CreateCommand())
        {
            command.CommandText = commandText;
            return command.ExecuteScalar();
        }
    }
}

using문은 예외가 발생하더라도 Dispose가 호출되도록합니다.

그러면 명령을 실행하는 것도 훨씬 쉽습니다.

value = connection.ExecuteScalar(commandText)
// Command object created and disposed


답변

유사한 문제가 있었지만 가비지 수집기 솔루션으로 해결되지 않았습니다.

사용 후 폐기 SQLiteCommandSQLiteDataReader개체를 발견 하면 가비지 수집기를 사용하여 전혀 구할 수 없었습니다.

SQLiteCommand command = new SQLiteCommand(sql, db);
command.ExecuteNonQuery();
command.Dispose();


답변

다음은 나를 위해 일했습니다.

MySQLiteConnection.Close();
SQLite.SQLiteConnection.ClearAllPools()

추가 정보 : 연결은 성능 향상을 위해 SQLite에 의해 풀링됩니다. 즉, 연결 개체에서 Close 메서드를 호출하면 데이터베이스에 대한 연결이 여전히 활성화되어 (백그라운드에서) 다음 Open 메서드가 더 빨라질 수 있습니다. 더 이상 새 연결을 원하지 않는 경우 ClearAllPools를 호출하면 백그라운드에 살아있는 모든 연결이 닫히고 db 파일에 대한 파일 핸들이 해제됩니다. 그런 다음 db 파일이 제거, 삭제 또는 다른 프로세스에서 사용될 수 있습니다.


답변

비슷한 문제가 발생하여 해결책을 시도했지만 GC.Collect언급했듯이 파일이 잠기지 않는 데 오랜 시간이 걸릴 수 있습니다.

SQLiteCommandTableAdapters에서 기본 s 처리와 관련된 대체 솔루션을 찾았습니다 . 자세한 내용 은 이 답변 을 참조하십시오 .


답변

이것을 시도하십시오 … 이것은 위의 모든 코드를 시도합니다 … 나를 위해 일했습니다.

    Reader.Close()
    connection.Close()
    GC.Collect()
    GC.WaitForPendingFinalizers()
    command.Dispose()
    SQLite.SQLiteConnection.ClearAllPools()

도움이되는 희망