首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在SQLite中使用Massive时出现“数据库被锁定”异常

在SQLite中使用Massive时出现“数据库被锁定”异常
EN

Stack Overflow用户
提问于 2013-03-25 17:13:26
回答 1查看 1.7K关注 0票数 3

最近我浏览了一下micro,我喜欢用于SQLite的Massive,因为它很简单。但我现在有个问题。

我只是运行一些select语句,后跟一个update语句,但是我得到了一个异常。下面是我的代码:

代码语言:javascript
运行
复制
 var tbl = new Cust();
            var customers = tbl.All(where: "CustomerID > @0", orderBy: "FirstName", columns: "CustomerID,FirstName", args: 4);
            var firstCustomerName= customers.First().FirstName;

            var c = tbl.Update(new { FirstName = "Updated2" }, 4); //Exception is here!

            //Same happens even when using another object
            //var tbl2 = new Cust();
            //tbl2.Update(new { FirstName = "UpdatedName" }, 4);//Exception is here!

在Massive.SQLite源代码中的以下方法中,异常消息是:“数据库已锁定”

代码语言:javascript
运行
复制
public virtual int Execute(IEnumerable<DbCommand> commands)
{
       var result = 0;
            using (var conn = OpenConnection())
            {
                using (var tx = conn.BeginTransaction())
                {
                    foreach (var cmd in commands)
                    {
                        cmd.Connection = conn;
                        cmd.Transaction = tx;
                        result += cmd.ExecuteNonQuery();
                    }
                    tx.Commit();//Here is the Exception!
                }
            }
            return result;     
}

当我查看Massive.SQLite源代码时,我发现massive从不关闭连接,而是依赖using语句来处理connection对象,正如您在上面的代码中所看到的那样。

上面代码中的OpenConnection()是一个方法,它在每次调用时都返回一个新的连接。

代码语言:javascript
运行
复制
 public virtual DbConnection OpenConnection()
 {
            var result = _factory.CreateConnection();
            result.ConnectionString = ConnectionString;
            result.Open();
            return result;
 }

如果情况是case没有关闭连接,并且根据this SO question Sqlite不擅长并发连接,而我应该关闭它,那么我如何关闭它呢?-连接不会暴露给我。

我想听听开发人员在SQLite中使用Massive的最佳实践。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-04-14 21:33:51

SQlite喜欢只有一个打开的连接。

Massive正在正确地管理连接,但是它在Query method中保留了“打开”的ExecuteReader,这可以cause troubles:

罗伯特·辛普森写道:

打开阅读器可能会导致问题。在懒惰的垃圾收集器找到它之前,这些是不会被清理的。在任何情况下,至少在读者周围使用using()语句肯定会更好。以下对象使用垃圾收集器懒于清理的非托管资源:

SQLiteCommand、SQLiteConnection、SQLiteDataReader,如果我没记错的话,可能还有SQLiteTransaction。

因此,在Query方法中的ExecuteReader()周围放置一个using,它应该可以很好地工作:

代码语言:javascript
运行
复制
public virtual IEnumerable<dynamic> Query(string sql, params object[] args)
{
    using (var conn = OpenConnection())
    {
        using (var rdr = CreateCommand(sql, conn, args).ExecuteReader())
        {
            while (rdr.Read())
            {
                yield return rdr.RecordToExpando(); ;
            }
        }
    }
}

一些注释和其他不需要更改大量源代码的解决方法:

  • 您可以使用Pooling设置在SQLite中启用连接池:

connectionString="Data Source=test.db;Version=3;Pooling=True;Max Pool Size=100;"

  • the Query通常工作正常,如果它从读取器读取所有数据。但您使用的是First(),它与yield return相结合,使阅读器处于开放状态。因此,如果您使用ToArray()计算查询,它也会起作用:

customers.ToArray().First().FirstName; firstCustomerName= var

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15611179

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档