3

Windows 8 リリース プレビューと C#(VS 2012) を使用してメトロ アプリを開発しています。SQLite は初めてです。アプリに SQLite 3.7.13 を統合しましたが、正常に動作しています。

var dbPath = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "Test.db");
using (var db = new SQLite.SQLiteConnection(dbPath))
{                       
    var data = db.Table<tablename>().Where(tablename => tablename.uploaded_bool == false && tablename.Sid == 26);
    try
    {
        int iDataCount = data.Count();
        int id;                        
        if (iDataCount > 0)
        {                  
            for (int i = 0; i < iDataCount; i++)
            {
                Elements = data.ElementAt(i);
                id = Elements.id;
                /*
                Doing some code
                */                                               
            }     
             int i = db.Delete<tablename>(new tablename() { Sid = 26 });
        }
    }
    catch (Exception ex)
    {

    }
}   

ここで、「Sid」はデータベースの列で、番号「26」で n 個の行を取得します。したがって、for ループを使用してコードを実行する必要があり、for ループの後に Sid(26) のレコードを削除する必要がありますデータベースなので、この行で

int i = db.Delete<tablename>(new tablename() { Sid = 26 });

例外が発生してunable to close due to unfinalised statementsいます。私の質問は、sqlite3 でステートメントをファイナライズする方法です。どうやら SQLite3 には、以前の DB 呼び出しを破棄するためのファイナライズ メソッドがありますが、これを実装する方法がわかりません。私を助けてください。

4

1 に答える 1

2

内部では、sqlite-net はクエリと接続を管理するためにいくつかの驚くべきことを行っています。

たとえば、次の行

var data = db.Table<tablename>().Where(...)

実際に接続を確立したり、データベースに対して何かを実行したりすることはありません。代わりに、列挙可能な TableQuery というクラスのインスタンスを作成します。

電話すると

int iDataCount = data.Count();

TableQuery が実際に実行される

GenerateCommand("count(*)").ExecuteScalar<int>();

電話すると

Elements = data.ElementAt(i);

TableQuery が実際に呼び出す

return Skip(index).Take(1).First();

Take(1).First()は最終的にGetEnumeratorを呼び出します。これにより、SQLite コマンドがコンパイルされ、TOP 1 で実行され、結果がシリアル化されてデータ クラスに戻されます。

したがって、基本的に、data.ElementAtを呼び出すたびに、別のクエリを実行しています。これは、コレクションまたは配列内の要素にアクセスするだけの標準の .NET 列挙とは異なります。

これがあなたの問題の根源だと思います。カウントを取得してfor(i, ...)ループを使用する代わりに、単にforeach (tablename tn in data)を実行することをお勧めします。これにより、ループ内のレコードごとではなく、すべてのレコードが一度にフェッチされます。それだけで、クエリを閉じて、ループ中にテーブルを削除できるようにするのに十分な場合があります。そうでない場合は、コレクションを作成し、ループ中に各 SID をコレクションに追加することをお勧めします。次に、ループが戻った後、別のパスで sid を削除します。最悪の場合、ループ間の接続を閉じることができます。

それが役立つことを願っています。

于 2012-08-21T15:26:00.243 に答える