[英]“Database is locked” exception when using Massive with SQLite
最近我瀏覽了微型ORM,我喜歡Massive for SQLite,因為它很簡單。 但我現在有一個問題。
我只是運行一些select語句后跟一個更新語句,但我得到一個例外。 以下是我的代碼:
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源代碼時,我看到大量從不關閉連接,而是繼續使用using語句來處理連接對象,如上面的代碼所示。
上面代碼中的OpenConnection()是一種每次調用時都返回一個新連接的方法。
public virtual DbConnection OpenConnection()
{
var result = _factory.CreateConnection();
result.ConnectionString = ConnectionString;
result.Open();
return result;
}
如果案例是Massive沒有關閉連接,並根據這個SO問題 Sqlite不擅長並發連接,我應該關閉它,我怎么能關閉它呢? - 連接不會暴露給我。
我想聽聽開發人員使用Massive和SQLite的最佳實踐。
SQlite喜歡打開一個連接。
Massive正確管理連接,但它在Query方法中將ExecuteReader
“open”,這可能會導致麻煩:
羅伯特辛普森寫道:
讓讀者保持開放可能會導致問題。 在懶惰的垃圾收集器到達它之前,這些將不會被清理干凈。 在任何情況下,至少在讀者周圍使用using()語句肯定會更好。 以下對象使用垃圾收集器將在清理時懶惰的非托管資源:
如果我沒記錯的話,SQLiteCommand,SQLiteConnection,SQLiteDataReader以及可能的SQLiteTransaction。
因此,在Query
方法中using
ExecuteReader()
,它應該可以正常工作:
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 return
讓讀者打開了。 因此,如果您使用ToArray()
評估查詢,它也將起作用:
var firstCustomerName= customers.ToArray().First().FirstName;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.