最近我浏览了一下micro,我喜欢用于SQLite的Massive,因为它很简单。但我现在有个问题。
我只是运行一些select语句,后跟一个update语句,但是我得到了一个异常。下面是我的代码:
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源代码中的以下方法中,异常消息是:“数据库已锁定”
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()是一个方法,它在每次调用时都返回一个新的连接。
public virtual DbConnection OpenConnection()
{
var result = _factory.CreateConnection();
result.ConnectionString = ConnectionString;
result.Open();
return result;
}
如果情况是case没有关闭连接,并且根据this SO question Sqlite不擅长并发连接,而我应该关闭它,那么我如何关闭它呢?-连接不会暴露给我。
我想听听开发人员在SQLite中使用Massive的最佳实践。
发布于 2013-04-14 21:33:51
SQlite喜欢只有一个打开的连接。
Massive正在正确地管理连接,但是它在Query method中保留了“打开”的ExecuteReader
,这可以cause troubles:
罗伯特·辛普森写道:
打开阅读器可能会导致问题。在懒惰的垃圾收集器找到它之前,这些是不会被清理的。在任何情况下,至少在读者周围使用using()语句肯定会更好。以下对象使用垃圾收集器懒于清理的非托管资源:
SQLiteCommand、SQLiteConnection、SQLiteDataReader,如果我没记错的话,可能还有SQLiteTransaction。
因此,在Query
方法中的ExecuteReader()
周围放置一个using
,它应该可以很好地工作:
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;"
Query
通常工作正常,如果它从读取器读取所有数据。但您使用的是First()
,它与yield return
相结合,使阅读器处于开放状态。因此,如果您使用ToArray()
计算查询,它也会起作用:customers.ToArray().First().FirstName; firstCustomerName= var
https://stackoverflow.com/questions/15611179
复制相似问题