2009-07-22 48 views
3

私はasp.net c#を使用していて、SqLiteデータベースをサーバーにアップロードしてから、挿入と更新を行います。問題は、データベースがロックされることがある(時々、それが更新されているかどうかに間違っていると思う)ことです。次回にファイルをアップロードしようとすると、ロックされ、「別のプロセスで使用されているため、プロセスはファイルにアクセスできません」というエラーが表示されます。トランザクション中に何か問題が発生した場合、データベースファイルが破棄されないことがありますか?この問題を解決する唯一の方法は、サーバーを再起動することです。Sqliteデータベースがロックされました

私のコードでどのように解決できますか?何か問題が発生しても常にロックされていることを確認できますか?

これは私のコードです:

try 
{ 
    string filepath = Server.MapPath("~/files/db.sql"); 

    //Gets the file and save it on the server 
    ((HttpPostedFile)HttpContext.Current.Request.Files["sqlitedb"]).SaveAs(filepath); 

    //Open the database 
    SQLiteConnection conn = new SQLiteConnection("Data Source=" + filepath + ";Version=3;"); 

    conn.Open(); 
    SQLiteCommand cmd = new SQLiteCommand(conn); 
    using (SQLiteTransaction transaction = conn.BeginTransaction()) 
    { 
    using (cmd) 
    { 
     //Here I do some stuff to the database, update, insert etc 
    } 
    transaction.Commit(); 
    } 
    conn.Close(); 
    cmd.Dispose(); 
} 
catch (Exception exp) 
{ 
//Error 
} 
+0

スレッドを使用していますか? –

+0

どのようにスレッド?私のasp.netコードでは、sqliteのコードではわからないが、私はそうは思わない? –

+1

明示的に作成していない場合でも、asp.netはマルチスレッドです。他のユーザーからのリクエストをasp.netがどのように処理できるのでしょうか? sqlite dbを変更すると、完全なdbがロックされます。あなたはsqliteでマルチスレッドの読み込みを行うことができますが、書き込み(挿入、更新、削除、テーブル作成)はデータベース全体をロックします。あなたは.net readerwriter-lockクラスを使わなければならないと思います。 – tuinstoel

答えて

2

あなたが同様に使用してブロック内の接続を配置する、またはそれに処分を呼び出してみてください:

//Open the database 
using (SQLiteConnection conn = new SQLiteConnection("Data Source=" + filepath + ";Version=3;")) { 
    conn.Open(); 
    using (SQLiteCommand cmd = new SQLiteCommand(conn)) { 
    using (SQLiteTransaction transaction = conn.BeginTransaction()) { 
     //Here I do some stuff to the database, update, insert etc 
     transaction.Commit(); 
    } 
    } 
} 

これは、あなたが処分していることを保証します接続オブジェクトの正しい(あなたは現時点ではなく、閉じているだけです)。

ブロックを使用して、それらをラップは、例外が発生した場合でも廃棄が呼び出されることを保証します - それは効果的に書き込みと同じです:

// Create connection, command, etc objects. 
SQLiteConnection conn; 

try { 
    conn = new SQLiteConnection("Data Source=" + filepath + ";Version=3;"); 
    // Do Stuff here... 
} 
catch (exception e) { 
    // Although there are arguments to say don't catch generic exceptions, 
    // but instead catch each explicit exception you can handle. 
} 
finally { 
    // Check for null, and if not, close and dispose 
    if (null != conn) 
    conn.Dispose(); 
} 

finallyブロック内のコードは関係なく、例外のと呼ばれるように起こっています、クリーンアップに役立ちます。

+0

ありがとう!! 私が使用する場合: "throw e;"私のキャッチでは、それは例外をスローする前に、最後の部分はまだ実行されますか? –

+1

はい:http://msdn.microsoft.com/en-us/library/xhcbs8fz.aspx –

0

cmd.Dispose()の前に、conn.Close()を入力してください。私はそれが何か違いがあるかどうかは分かりませんが、一般的には初期化の順序の反対に物事をきれいにしたいと思っています。

0

つまり、SQLiteは管理されていないリソースを他のプロバイダと少しずつ処理します。あなたが使用して()ブロックの外側でリーダーで作業している場合でも動作するように思われる(明示的にコマンドを配置する必要があります

より味のために、このスレッドを読む。 http://sqlite.phxsoftware.com/forums/p/909/4164.aspx

1

ASP。ネットアプリケーションがサーバーにマルチスレッド化されています。

DB全体がロックされているので、あなたは、同時書き込み(挿入、選択、更新を...)行うことはできません。何も書き込みが起こっていないときに同時に選択が許可されている。

.NET ReaderWriterLockクラスを使用する必要があります。http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlock.aspx

関連する問題