Использование базы данных Flutter Isar в модели

В настоящее время я создаю базу данных с помощью Isar, которая выглядит следующим образом:

      
@collection
class Polygon {
  Id id = Isar.autoIncrement;

  final vertices = IsarLinks<Vertex>();

  late Color color;
}

@collection
class Vertex {
  Id id = Isar.autoIncrement;

  final polygon = IsarLink<Polygon>();

  late Offset point;
}

В моем коде у меня есть изображение, на котором я рисую эти многоугольники, используя событие GestureDetector onTapUp:

      List<Vertex>? _currentVertices;

void addVertex(details) async {
    Offset pos = details.localPosition;

    if (_currentVertices == null) {
      _currentVertices = [Vertex()..point = pos];
    } else {
      if (_currentVertices!.length > 2 &&
        (_currentVertices!.first.point - pos).distance <= 20 ) {

        // Create a new polygon from the list of vertices and save it to the database
        Polygon p = Polygon();

        // Set the polygon for each vertex
        for (var v in _currentVertices!) {
          v.polygon.value = p;
        }

        // Save it into the database
        await _isar.writeTxn(() async {
          await _isar.polygons.put(p);
        });

        _currentVertices = null;
      } else {
        // Add point to current list of vertices
        _currentVertices!.add(Vertex()..point = pos);
      }
    }
  }

Но когда я это сделаю, многоугольник появится в базе данных, а вершины — нет. Итак, я попробовал:

          await _isar.writeTxn(() async {
      await _isar.polygons.put(p);
    });

    for (var v in _currentVertices!) {
      await _isar.writeTxn(() async {
        await _isar.vertexs.put(v);
      });
    }

Теперь и полигоны, и вершины находятся в базе данных, но идентификаторы/IsarLinks не установлены...

  1. Есть ли у кого-нибудь пример того, как вам следует это сделать?

Во-вторых:

На самом деле я читал об использовании провайдера здесь (внутри класса PolygonModel). Итак, как только у меня появится класс PolygonModel (чтобы мое представление могло отслеживать изменения в полигонах), мне понадобится метод PolygonModel.addPolygon(p).

Должен ли я реализовать как модель Polygon, так и модель Vertex? На самом деле мне не нужна модель Vertex в качестве уведомления об изменениях, так что это кажется излишним. Так что я должен просто сделать:

              // Create a new polygon from the list of vertices and save to the database
        Polygon p = Polygon();

        for (var v in _currentVertices!) {
          v.polygon.value = p;
        }

        // Add both the polygon and vertices to the database
        polygonModel.addPolygon(p, _currentVertices!);

Или мне действительно нужно сделать что-то вроде:

              // Create a new polygon from the list of vertices and save to the database
        Polygon p = Polygon();

        polygonModel.addPolygon(p);

        for(var v in _currentVertices!) {
          vertexModel.addVertex(p, v);
        }

Опять же, были бы полезны любые ссылки на подходящие примеры подобной реализации (сейчас я собирался использовать провайдер/провайдер.dart, но также читал о Riverpod, который может быть лучшим решением).

1 ответ

Хорошо, я думаю, что решил эту проблему, реальная проблема в том, что я перешел с синхронных транзакций на асинхронные...

Isar автоматически сохраняет все IsarLinks в компоненте, когда вы используете синхронную транзакцию, а не асинхронную... Таким образом, частью решения является правильное сохранение элементов IsarLink компонента при сохранении компонента. Итак, если бы, например, у меня был родительский компонент многоугольного компонента, имеющий связь один к одному, вы бы сделали:

              // Save it into the database
        await _isar.writeTxn(() async {
          await _isar.parents.put(parent);
          await parent.polygon.save();
        });

Это сохранит новый родительский объект в базе данных isar, а затем сохранит IsarLink в полигоне (где на каждого родителя приходится один полигон).

Чтобы решить проблему с IsarLinks to Vertex, я пошел простым путем и вместо этого использовал встроенный:

      @collection
class Parent {
  Id id = Isar.autoIncrement;
  final polygon = IsarLink<Polygon>();
}

@collection
class Polygon {
  Id id = Isar.autoIncrement;

  List<Vertex>? vertices;
}

@embedded
class Vertex {
  late double x;
  late double y;
}

На самом деле это не обман, потому что это правильный способ сделать такую ​​вещь (вершины не являются общими для разных полигонов). Но это также означает, что я обхожу сохранение IsarLinks. Но я вернусь к этому как-нибудь позже... Комментарии будут полезны.

Второй выпуск:

Опять же, я использовал самое простое решение. Поскольку вершины на самом деле теперь представляют собой просто список «встроенных», они автоматически сохраняются вместе с многоугольником. Я не уверен, что действительно ответил на свои вопросы, но надеюсь, что кто-то еще сможет поучиться здесь из моих мыслей.

Другие вопросы по тегам