sqlite - Flutter Sqflite 多表模型

标签 sqlite dart flutter singleton

我已经阅读了许多关于如何在 Flutter 中实现 Sqflite 的教程和示例。其他所有示例都是仅使用一个模型或数据库表完成的。如这些教程中所定义:

https://pub.dartlang.org/packages/sqflite

https://www.developerlibs.com/2018/07/flutter-sqlite-database-example.html

http://camposha.info/flutter/sqflite-insert-select-show

据我所知,我们需要创建与表一样多的模型和助手。对于每个数据库表,将有一个 model.dart 文件和一个 helper.dart 文件。

我的问题是,有什么方法可以让所有模型都只有一个助手吗?

更新

在 helper.dart 文件中有一个 future 的“插入”。如何对所有模型使用相同的插入 future ?

Future<Todo> insert(Todo todo) async {
    todo.id = await db.insert(tableTodo, todo.toMap());
    return todo;
}

最佳答案

我提出了一些相反的意见,但我只记得在我的上一个项目中我做了类似的事情,它是针对 Firebase 数据库,但它与 sqflite< 非常相似/strong>.

我创建了一个 BaseItem 抽象类,带有一个 key,所有模型都将派生自那个。

我还创建了一个 BaseProvider 抽象类,它需要一个 BaseItem 并定义访问模型的简单方法。

upsertdelete 方法位于 FirebaseBaseProvider 中,它扩展了 BaseProvider

我将在此处粘贴部分内容(删除了很​​多内容以使其更易于理解):

abstract class BaseItem {
  const BaseItem({this.key});
  final String key;
}

abstract class BaseProvider<T extends BaseItem> {
  Future<List<T>> find();

  Future<BaseKey> upsert(T item);

  Future<int> delete(T item);
}


abstract class FirebaseBaseProvider<T extends BaseItem> {
  // Abstract methods which need to be implemented
  T fromMap(BaseKey key, dynamic map);
  Map<String, dynamic> toJson(BaseKey key, T item);

  Future<DatabaseReference> getReference(BaseKey base) async { ... }    
  BaseKey compileKey(T item, {String useKey}) { ... }

  Future<List<T>> find() async {
    List<T> result = new List();
    // my implementation doesnt work like this, 
    // as it's firebase based, but this would
    // be the place in a Sqflite implementation to use
    // fromMap and load the items
    return result;
  }

  Future<BaseKey> upsert(T item) async {
    if (item == null) return null;

    BaseKey key = compileKey(item);
    (await getReference(key)).set(toJson(key, item));
    return key;
  }

  Future<int> delete(T item) async {
    if (item == null) return null;

    if (item.key != null && item.key != "") {
      (await getReference(compileKey(item))).remove();
    }
    return 0;
  }
}

然后,为了实现 News 模型或任何其他模型,我将通过简单地定义其内容来创建它,如下所示:

class News extends BaseItem {
  News({String key, this.creation, this.messageSubject, this.messageBody}) : super(key: key);

  final DateTime creation;
  final String messageSubject;
  final String messageBody;

  bool operator ==(o) => o is News && (o.key == key);
  int get hashCode => key.hashCode;
}

并且它需要它的特定提供者,它将只实现 toJsonfromMap 方法,就像这样:

class NewsProvider extends FirebaseBaseProvider<News> {
  @override
  Map<String, dynamic> toJson(BaseKey key, News news) {
    return {
      "creation": news.creation,
      "messageSubject": news.messageSubject,
      "messageBody": news.messageBody,
    };
  }

  @override
  News fromMap(BaseKey key, dynamic map) {
    DateTime creation = map["creation"] == null ? null : DateTime.tryParse(map["creation"] as String);

    return new News(
      key: key.child.key,
      creation: creation,
      messageSubject: map["messageSubject"] as String,
      messageBody: map["messageBody"] as String,
    );
  }
}

最后,NewProvider 提供了findupsertdelete 方法,但是它们的实现是在抽象类上,只需为所有模型实现它们的一个实现,如您所愿。

当然,我的实现比这复杂得多,因为 Firebase 需要不同的方法来获取/加载项目,而且 find 方法最终必须在每个模型中不同特定供应商。但是,很多事情都可以简化。

我在评论中所说的是最后一个类,即具有 toJsonfromMap 特定实现的特定 NewsProvider 也可能通过在 News 模型类中使用注解来泛化,但这会带来很多问题和晦涩,而且 - 当然是我认为 - 这不值得。

关于sqlite - Flutter Sqflite 多表模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53630564/

相关文章:

javascript - 如何以表格的形式用javascript显示数据库?

SQLite:排序我的选择结果

dart - 如何在 Dart 编程中监听键盘事件

android - 如何在 flutter 中创建自定义步进器?

listview - 如何在 Flutter 的粘性标题下对列表项进行分组

android - Android 的通用图像加载器可以处理来自 sqlite 数据库的图像吗?

java - 列 '_id' 不存在,嵌套查询的

flutter - 此函数的返回类型为 'Widget',但不以return语句结尾

dart - 从 RaisedButton 调用 FutureBuilder

google-maps - 在 Dart 中使用 google_maps_flutter 的 GestureDetector