sqliteは1つのトランザクションのみをサポートしますか?
-
05-07-2019 - |
質問
ADO.NETを使用している間(私は間違っているかもしれませんが、その名前がわからない)、接続でトランザクションを開始できるだけで、コマンドにはcommandが含まれているように見えますが、トランザクションデータは取得しますが、トランザクション自体を開始しますか?実際に見ながら、私はこれをSystem.Data.SQLiteで見る
// Summary:
// The transaction associated with this command. SQLite only supports one transaction
// per connection, so this property forwards to the command's underlying connection.
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public SQLiteTransaction Transaction { get; set; }
では、SQLiteは1つのトランザクション期間のみをサポートしていますか?別の接続を開こうとしましたが、DBがロックされているという例外がトランザクションからスローされました。だから、同時に複数の接続を持つことはできませんか?
解決
接続ごとに1つのトランザクション、はい。ただし、複数の接続を持つことができます(それぞれが独自のアクティブなトランザクションを持つ)。
更新:興味深い。共有キャッシュモードについては知りませんでした。接続がそのモードを使用している場合、同じ共有キャッシュを使用するすべての接続で使用できるトランザクションは1つだけです。 SQLite共有キャッシュモードを参照してください。
他のヒント
複数の接続についてはわかりませんが、SQLiteはサーバーベースのDBではなく、サーバーベースのDB(サーバーベースのDBすべてのファイルをロックし、同時接続を処理します。
一度に開くことができるトランザクションは1つだけです。 rollback
または commit
のいずれかになるまで、トランザクションの開始後に発生するすべてがそのトランザクション内にあるため、これは直感的な意味になります。その後、新しいものを開始できます。 SQLiteでは、すべてのコマンドがトランザクション内にある必要があるため、新しいコマンドを手動で開かない場合は自動的に開きます。
ネストされたトランザクションが心配な場合は、 savepoint
でそれらを偽造できます。 ドキュメント
1つのトランザクション内では、トランザクションが完了するまで1つの接続に対してのみ読み取り/書き込みができます。したがって、次のような複数のSQLステートメントにまたがるビジネストランザクションを行う場合は、接続オブジェクトを渡す必要があります。
public class TimeTableService
{
ITimeTableDataProvider _provider = new TimeTableDataProvider();
public void CreateLessonPlanner(WizardData wizardData)
{
using (var con = _provider.GetConnection())
using (var trans = new TransactionScope())
{
con.Open();
var weekListA = new List<Week>();
var weekListB = new List<Week>();
LessonPlannerCreator.CreateLessonPlanner(weekListA, weekListB, wizardData);
_provider.DeleteLessonPlanner(wizardData.StartDate, con);
_provider.CreateLessonPlanner(weekListA, con);
_provider.CreateLessonPlanner(weekListB, con);
_provider.DeleteTimeTable(TimeTable.WeekType.A, con);
_provider.StoreTimeTable(wizardData.LessonsWeekA.ToList<TimeTable>(), TimeTable.WeekType.A, con);
_provider.DeleteTimeTable(TimeTable.WeekType.B, con);
_provider.StoreTimeTable(wizardData.LessonsWeekB.ToList<TimeTable>(), TimeTable.WeekType.B, con);
trans.Complete();
}
}
}
接続およびトランザクションのリソースは、using-statementによって自動的に解放/クローズされます。
すべてのデータプロバイダーメソッドで実行します
using(var cmd = new SQLiteCommand("MyStatement",con)
{
// Create params + ExecuteNonQuery
}
TransactionScopeクラスは.NET 3.5で新しく追加され、例外が発生した場合に自動的にロールバックを実行します。簡単な処理...