3

最近、私はマイクロORMを閲覧していますが、シンプルなため、MassiveforSQLiteが好きです。しかし、私は今問題を抱えています。

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ステートメントを中継して接続オブジェクトを破棄していることがわかります。

上記のコードのOpenConnection()は、呼び出されるたびに新しい接続を返すメソッドです。

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

Massiveが接続を閉じていない場合で、このSOの質問によると、 Sqliteは同時接続が得意ではなく、閉じることになっている場合、どうすれば閉じることができますか?-接続は私に公開されていません。

MassiveとSQLiteを使用している開発者からのベストプラクティスを聞きたいです。

4

1 に答える 1

4

SQliteは、単一の接続を開くのが好きです。

Massiveは接続を正しく管理していますが、 QueryメソッドExecuteReaderに「オープン」のままであるため、問題が発生する可能性があります。

ロバートシンプソンは書いた:

リーダーを開いたままにしておくと、問題が発生する可能性があります。怠惰なガベージコレクターがそれに近づくまで、それらはクリーンアップされません。いずれにせよ、少なくとも読者の周りにusing()ステートメントがある方が確かに良いでしょう。次のオブジェクトは、ガベージコレクターがクリーンアップについて怠惰になるアンマネージリソースを使用します。

SQLiteCommand、SQLiteConnection、SQLiteDataReader、そして正しく思い出せばSQLiteTransactionかもしれません。

したがって、メソッドにusing周りを入れれば、正常に機能するはずです。ExecuteReader()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ソースを変更する必要のないいくつかのメモおよびその他の回避策:

  • Pooling次の設定を使用して、SQLiteで接続プールを有効にできます。

    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 に答える