System.Data.SQLite Close ()가 데이터베이스 파일을 해제하지 않습니다.
파일을 삭제하기 전에 데이터베이스를 닫는 데 문제가 있습니다. 코드는
myconnection.Close();
File.Delete(filename);
그리고 삭제는 파일이 아직 사용 중이라는 예외를 발생했습니다. 몇 분 후에 디버거에서 삭제 ()를 다시 시도해 타이밍 문제가 아닙니다.
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를 삭제하려고 할 때 예외가 발생했습니다.
어쨌든, 오늘 오후에 나는 모든 것을 다시 그렇게하는 것이 왜 단번에 그렇게했는지 알아 내고 노력할 생각했습니다. 그래서 여기에 제가 지금까지 그것이 있습니다.
호출 하면 SQLite 데이터베이스 인스턴스를 여러 SQLiteConnection.Close()
검사 및 기타 사항과 함께 SQLiteConnectionHandle
처리합니다. 이 작업은에 대한 호출을 통해 SQLiteConnectionHandle.Dispose()
수행 할 때까지 CLR의 가비지 수집기가 일부 가비지 수집을 수행 할 때까지 호출을 해제하지 않습니다. (다른 함수를 통해) 호출 SQLiteConnectionHandle
할 CriticalHandle.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
명시 적으로 삭제하지 않고 object-를 생성 했습니다.
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
다음은 나를 위해 일했습니다.
MySQLiteConnection.Close();
SQLite.SQLiteConnection.ClearAllPools()
추가 정보 : 연결은 성능 향상을 위해 SQLite에 의해 풀링됩니다. 즉, 연결 개체에서 Close 메서드를 호출하면 데이터베이스에 대한 연결이 여전히 활성화되어 (백그라운드에서) 다음 Open 메서드가 더 빨라질 수 있습니다. 더 이상 새 연결을 사용하지 않는 파일 경우 ClearAllPools를 호출하면 백그라운드에서 모든 연결이 닫히고 db 파일 핸들이 해제됩니다. 그런 다음 db 파일이 제거되거나 삭제되거나 다른 프로세스에서 수 있습니다.
해결할 문제가 있었지만 가비지 수집기 솔루션으로 해결되지 않았습니다.
사용 후 폐기 SQLiteCommand
및 SQLiteDataReader
개체를 발견 하면 가비지 수집기를 사용하여 전혀 구할 수 없습니다.
SQLiteCommand command = new SQLiteCommand(sql, db);
command.ExecuteNonQuery();
command.Dispose();
많은 문제가 발생하여 파일을 시도했던 GC.Collect
적이 있었는데 오랜 시간이 있습니다.
SQLiteCommand
TableAdapters에서 기본 s 처리와 관련된 대체 솔루션을 찾았습니다 . 자세한 내용 은 이 답변 을 참조하십시오 .
모든 시도하십시오 ...이 위의 코드를 시도합니다 ... 나를 위해 일했습니다.
Reader.Close()
connection.Close()
GC.Collect()
GC.WaitForPendingFinalizers()
command.Dispose()
SQLite.SQLiteConnection.ClearAllPools()
도움이되는 희망
사용하다 GC.WaitForPendingFinalizers()
예 :
Con.Close();
GC.Collect();`
GC.WaitForPendingFinalizers();
File.Delete(Environment.CurrentDirectory + "\\DATABASENAME.DB");
신고 문제가 있습니다. 가비지 수집기를 호출해도 도움이되지 않습니다. 나중에 문제를 방법을 찾았습니다.
작성자는 또한 데이터베이스를 삭제하기 전에 해당 데이터베이스에 SELECT 쿼리를 수행하고 사용했습니다. 저도 같은 상황입니다.
다음 코드가 있습니다.
SQLiteConnection bc;
string sql;
var cmd = new SQLiteCommand(sql, bc);
SQLiteDataReader reader = cmd.ExecuteReader();
reader.Read();
reader.Close(); // when I added that string, the problem became solved.
또한 연결 데이터베이스를 닫고 가비지 수집기를 호출 할 필요가 없습니다. 내가해야 할 일은 생성되는 SELECT 쿼리를 실행하는 동안 생성 된 리더를 닫는 것입니다.
GC는 전혀 다룰 필요가 없습니다. 모든 것이 sqlite3_prepare
완료했는지 확인하십시오 .
각각 sqlite3_prepare
에 대해 특파원이 필요합니다 sqlite3_finalize
.
문서 마무리하지 문서 sqlite3_close
연결이 닫히지 언어로 연결됩니다.
나는 EF와 System.Data.Sqlite
.
나를 위해 파일 잠금이 발생하는 빈도를 발견 SQLiteConnection.ClearAllPools()
하고 GC.Collect()
수 있었지만 여전히 가끔 발생합니다 (약 1 % 시간).
나는 조사를 해왔고 SQLiteCommand
EF가 생성 하는 일부 는 폐기되지 않았고 여전히 Connection 속성이 닫힌 연결로 설정된 것 같습니다. 나는 이것을 폐기하려고 시도했지만 Entity Framework는 다음 DbContext
읽기 중에 예외를 throw합니다. EF는 연결이 닫힌 후에도 여전히 사용하는 것 같습니다.
내 솔루션은 Null
연결이 이러한 SQLiteCommand
s에서 닫힐 때 Connection 속성이로 설정되어 있는지 확인하는 것 입니다. 이것은 파일 잠금을 해제하기에 충분한 것 같습니다. 아래 코드를 테스트했지만 수천 번의 테스트 후에도 파일 잠금 문제를 보지 못했습니다.
public static class ClearSQLiteCommandConnectionHelper
{
private static readonly List<SQLiteCommand> OpenCommands = new List<SQLiteCommand>();
public static void Initialise()
{
SQLiteConnection.Changed += SqLiteConnectionOnChanged;
}
private static void SqLiteConnectionOnChanged(object sender, ConnectionEventArgs connectionEventArgs)
{
if (connectionEventArgs.EventType == SQLiteConnectionEventType.NewCommand && connectionEventArgs.Command is SQLiteCommand)
{
OpenCommands.Add((SQLiteCommand)connectionEventArgs.Command);
}
else if (connectionEventArgs.EventType == SQLiteConnectionEventType.DisposingCommand && connectionEventArgs.Command is SQLiteCommand)
{
OpenCommands.Remove((SQLiteCommand)connectionEventArgs.Command);
}
if (connectionEventArgs.EventType == SQLiteConnectionEventType.Closed)
{
var commands = OpenCommands.ToList();
foreach (var cmd in commands)
{
if (cmd.Connection == null)
{
OpenCommands.Remove(cmd);
}
else if (cmd.Connection.State == ConnectionState.Closed)
{
cmd.Connection = null;
OpenCommands.Remove(cmd);
}
}
}
}
}
사용하려면 ClearSQLiteCommandConnectionHelper.Initialise();
응용 프로그램로드 시작시 호출 하십시오. 그러면 활성 명령 목록이 유지되고 Null
닫힌 연결을 가리킬 때 연결이로 설정됩니다 .
나는 그 요청 SQLite.SQLiteConnection.ClearAllPools()
이 가장 깨끗한 해결책 이라고 믿습니다 . 내가 아는 GC.Collect()
한 WPF 환경에서 수동으로 호출하는 것은 적절하지 않습니다 . 하지만 System.Data.SQLite
2016 년 3 월에 1.0.99.0으로 업그레이드 할 때까지 문제를 인지하지 못했습니다.
나는 비슷한 문제로 어려움을 겪고 있었다. 부끄러워 ... 마침내 Reader 가 닫히지 않았다는 것을 깨달았 습니다. 어떤 이유로 해당 연결이 닫히면 리더가 닫힐 것이라고 생각했습니다. 분명히 GC.Collect ()는 나를 위해 작동하지 않았습니다.
Reader를 "using : 문으로 감싸는 것도 좋은 생각입니다. 여기에 간단한 테스트 코드가 있습니다.
static void Main(string[] args)
{
try
{
var dbPath = "myTestDb.db";
ExecuteTestCommand(dbPath);
File.Delete(dbPath);
Console.WriteLine("DB removed");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
Console.Read();
}
private static void ExecuteTestCommand(string dbPath)
{
using (var connection = new SQLiteConnection("Data Source=" + dbPath + ";"))
{
using (var command = connection.CreateCommand())
{
command.CommandText = "PRAGMA integrity_check";
connection.Open();
var reader = command.ExecuteReader();
if (reader.Read())
Console.WriteLine(reader.GetString(0));
//without next line database file will remain locked
reader.Close();
}
}
}
EF6에서 SQLite 1.0.101.0을 사용하고 있었고 모든 연결과 엔티티가 삭제 된 후 파일이 잠기는 문제가 발생했습니다.
이것은 EF의 업데이트가 완료된 후 데이터베이스를 잠근 상태로 유지하면서 악화되었습니다. GC.Collect ()는 도움이 된 유일한 해결 방법이었고 절망하기 시작했습니다.
필사적으로 Oliver Wickenden의 ClearSQLiteCommandConnectionHelper를 사용해 보았습니다 (7 월 8 일 그의 답변 참조). 환상적입니다. 모든 잠금 문제가 사라졌습니다! 감사합니다 올리버.
가비지 콜렉터를 기다리는 동안 데이터베이스가 항상 해제되지 않을 수 있습니다. 예를 들어 PrimaryKey에 대한 기존 값이있는 행을 삽입하려고 시도하는 경우와 같이 SQLite 데이터베이스에서 일부 유형의 예외가 발생하면 사용자가 처리 할 때까지 데이터베이스 파일이 보관됩니다. 다음 코드는 SQLite 예외를 포착하고 문제가있는 명령을 취소합니다.
SQLiteCommand insertCommand = connection.CreateCommand();
try {
// some insert parameters
insertCommand.ExecuteNonQuery();
} catch (SQLiteException exception) {
insertCommand.Cancel();
insertCommand.Dispose();
}
문제가있는 명령의 예외를 처리하지 않으면 Garbage Collector가 처리 할 수없는 예외가 있습니다. 이러한 명령에 대해 처리되지 않은 예외가 있으므로 가비지가 아닙니다. 이 처리 방법은 가비지 수집기를 기다리는 데 잘 작동했습니다.
이것은 나를 위해 작동하지만 때로는 프로세스가 닫힐 때 저널 파일 -wal -shm이 삭제되지 않는 것으로 나타났습니다. 모든 연결이 닫 혔을 때 SQLite가 -wal -shm 파일을 제거하도록하려면 마지막 연결이 읽기 전용이 아니어야합니다. 이것이 누군가를 도울 수 있기를 바랍니다.
참고 URL : https://stackoverflow.com/questions/8511901/system-data-sqlite-close-not-releasing-database-file
'ProgramingTip' 카테고리의 다른 글
Java의 X509Certificate에서 CN을 추출하는 방법은 무엇입니까? (0) | 2020.10.04 |
---|---|
방법 : 사용자 지정 위젯에 대한 테마 (스타일) 항목 정의 (0) | 2020.10.04 |
오류 구문 분석 /page.xhtml : 오류 추적 [line : 42] "nbsp"가 참조되지 않습니다. (0) | 2020.10.04 |
Java에서 바이트 배열을 16 진수로 변환하는 방법은 무엇입니까? (0) | 2020.10.03 |
Android 개발 도구 v. 23으로 Eclipse 업데이트 (0) | 2020.10.03 |