3

我正在使用 Windows 8 发布预览版和 C#(VS 2012) 开发 Metro 应用程序,我是 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 有一个用于销毁以前的数据库调用的 finalize 方法,但我不确定如何实现这一点。请帮我。

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 添加到集合中。然后,在循环后返回并在另一遍中删除 sids。最坏的情况是,您可以关闭循环之间的连接。

希望有帮助。

于 2012-08-21T15:26:00.243 回答