3

Recently I browse the micro ORMs and I like Massive for SQLite because its simple. But I have now an issue.

I am just running some select statement followed by an update statement but I am getting an exception. Below is my code :

 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!

The Exception Message is : "Database is locked", at a method below in the Massive.SQLite source

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;     
}

When I look at Massive.SQLite source i see that massive never closes connections but instead relays on the using statement to dispose the connection object, as you can see in the above code.

OpenConnection() in the above code is a method that returns a new connection every time called.

 public virtual DbConnection OpenConnection()
 {
            var result = _factory.CreateConnection();
            result.ConnectionString = ConnectionString;
            result.Open();
            return result;
 }

If the case is that Massive is not closing the connection, and according to this SO question Sqlite is not good at concurrent connections and I am supposed to close it, how can I close it then? - the connection is not exposed to me.

I want to hear the best practice from developers using Massive with SQLite.

4

1 回答 1

4

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

Massive 正在正确管理连接,但它会在Query 方法中留下ExecuteReader“打开”状态,这可能会导致问题:

罗伯特辛普森写道:

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

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

所以在方法中加上一个usingExecuteReader()Query应该可以正常工作:

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(); ;
            }
        }
    }
}

一些不需要更改 Massive 源的注意事项和其他解决方法:

  • 您可以通过设置在 SQLite 中启用连接池Pooling

    connectionString="Data Source=test.db;Version=3;Pooling=True;Max Pool Size=100;"
    
  • 如果它从阅读器读取所有数据,通常Query可以正常工作。但是您使用了哪个结合左阅读器打开。因此,如果您使用它评估查询也将起作用:First()yield returnToArray()

    var firstCustomerName= customers.ToArray().First().FirstName;
    
于 2013-04-14T13:33:51.387 回答