Isarでトランザクションのネストエラーが発生した際の対処法

2024年6月21日金曜日

Flutter

t f B! P L

Isarデータベースライブラリを使用してDartまたはFlutterアプリケーションを開発する際、特定の状況で「IsarError: Cannot perform this operation from within an active transaction. Isar does not support nesting transactions.」というエラーが発生することがあります。この記事では、このエラーの原因とその対処方法を詳しく説明します。

エラーが発生したコード

このエラーは、Isarのトランザクション中にIsarLinksを使用してサブリストのアイテムに対して検索クエリ(例えばwhereクエリ)を行う場合に発生することがあります。例えば、タスクとサブタスクを管理する以下のようなモデルがあるとします。

()
class Task {
  Id id = Isar.autoIncrement;
  late String name;

  final subTasks = IsarLinks<SubTask>();
}

()
class SubTask {
  Id id = Isar.autoIncrement;
  late String name;
  late DateTime dueDate;
}

このモデルにおいて、以下のようなトランザクション内でサブタスクに対して検索を行うとエラーが発生します。

await isar.writeTxn(() async {
  var ret = task.subTasks
      .where((elem) => elem.dueDate == dateTime).firstOrNull;

  // その他の処理
});

エラーの原因

おそらく、IsarLinksのリンク集合にwhereを使用すると、内部で新たなトランザクションが暗黙のうちに開始され、既に開始されているトランザクションにネストしてしまうようです。Isarはネストしたトランザクションをサポートしていないため、この状況はエラーを引き起こします。

解決策

対処法として、whereを直接使用するのではなく、Isarが提供するより正式なクエリAPIを使用して検索を行います。以下は修正後のコードです。

await isar.writeTxn(() async {
  var ret = await task.subTasks
      .filter()
      .dueDateEqualTo(dateTime)
      .findFirst();

  // その他の処理
});

この方法では、filterを用いて具体的な条件を指定し、findFirstで条件に合致する最初の要素を取得します。このクエリはトランザクション内部で安全に実行され、ネストされたトランザクションを生成しません。

まとめ

Isarで「IsarError: Cannot perform this operation from within an active transaction.」というエラーに遭遇した場合は、検索クエリの書き方を見直して、内部で新たなトランザクションが開始されることがないように注意しましょう。

スポンサーリンク
スポンサーリンク

このブログを検索

Profile

自分の写真
Webアプリエンジニア。 日々新しい技術を追い求めてブログでアウトプットしています。
プロフィール画像は、猫村ゆゆこ様に書いてもらいました。

仕事募集もしていたり、していなかったり。

QooQ