如何将列表插入sqflite数据库列中

huangapple go评论57阅读模式
英文:

How can I insert the List in a column of sqflite database

问题

我正在处理一个Flutter项目,其中我有两个数据库,一个是在线数据库,使用Firestore数据库,另一个是本地数据库,使用sqflite数据库。

我的目标是,当用户启动应用程序时,它将从Firestore数据库中获取一个食谱集合,并将其存储在sqflite数据库中。

这是函数:

Future<List> getRecipeDataList() async {
    List recipes = [];
    int count = await getRecipeCount();
    int recipeID = 101;
    for (int i = 0; i < count; i++, recipeID++) {
        if (await checkIfRecipeDocExists(recipeID.toString()) == true) {
            QuerySnapshot<Map<String, dynamic>> recipesSnapshot = await FirebaseFirestore.instance.collection('recipes').get();
            for(QueryDocumentSnapshot<Map<String, dynamic>> doc in recipesSnapshot.docs){
                final data = doc.data();
                await LocalDatabase.instance.insertRecipe({
                    LocalDatabase.recipeID: 100,
                    LocalDatabase.recipe_name: data['recipe_name'],
                    LocalDatabase.recipe_description: data['recipe_description'],
                    LocalDatabase.recipeImageURL: data['recipeImageURL'],
                    LocalDatabase.recipe_rating: data['recipe_rating'],
                    LocalDatabase.recipe_time: data['recipe_time'],
                    LocalDatabase.recipe_ingredients: data['recipe_ingredients'],
                });
                recipes.add(
                    Recipes(
                        recipeID: doc.id,
                        recipeName: data['recipe_name'],
                        recipeDescription: data['recipe_description'],
                        recipeURL: data['recipeImageURL'],
                        recipeRating: data['recipe_rating'],
                        recipeTime: data['recipe_time'],
                        recipeIngredients: (data['recipe_ingredients'] as List<dynamic>).cast<String>(),
                    ),
                );
            }
        }
    }
    return recipes;
}

这是我的sqflite数据库类:

class LocalDatabase {
    // ...
    // (这里是你的数据库类代码)
    // ...
}

我遇到的错误是:

I/flutter (13393): *** WARNING *** I/flutter (13393):  I/flutter (13393): Invalid argument [Ingredients 1, Ingredients 2, Ingredients 3] with type List<dynamic>. I/flutter (13393): Only num, String and Uint8List are supported. See https://github.com/tekartik/sqflite/blob/master/sqflite/doc/supported_types.md for details I/flutter (13393):  I/flutter (13393): This will throw an exception in the future. For now it is displayed once per type. I/flutter (13393):  I/flutter (13393):      E/flutter (13393): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: DatabaseException(java.lang.String cannot be cast to java.lang.Integer) sql 'INSERT INTO recipes (recipeID, recipe_name, recipe_description, recipeImageURL, recipe_rating, recipe_time, recipe_ingredients) VALUES (?, ?, ?, ?, ?, ?, ?)' args [100, recipe_name, recipe_description, recipeImageURL, recipe_rating, recipe_time, [Ingredients 1, Ingredients 2, Ingredients 3]] E/flutter (13393): #0      wrapDatabaseException (package:sqflite/src/exception_impl.dart:11:7) E/flutter (13393): <asynchronous suspension> E/flutter (13393): #1     SqfliteDatabaseMixin.txnRawInsert.<anonymous closure> (package:sqflite_common/src/database_mixin.dart:548:14) E/flutter (13393): <asynchronous suspension> E/flutter (13393): #2     BasicLock.synchronized (package:synchronized/src/basic_lock.dart:33:16) E/flutter (13393): <asynchronous suspension> E/flutter (13393): #3     SqfliteDatabaseMixin.txnSynchronized (package:sqflite_common/src/database_mixin.dart:489:14) E/flutter (13393): <asynchronous suspension> E/flutter (13393): #4     LocalDatabase.insertRecipe (package:recipedia/WidgetsAndUtils/local_database.dart:56:12) E/flutter (13393): <asynchronous suspension> E/flutter (13393): #5    RecipeModel.getRecipeDataList (package:recipedia/WidgetsAndUtils/recipe_model.dart:78:11) E/flutter (13393): <asynchronous suspension> E/flutter (13393): #6     _LoginState.getRecipeData (package:recipedia/RegistrationAndLogin/login.dart:194:15) E/flutter (13393): <asynchronous suspension> E/flutter (13393):

阅读了这个错误后,我能够识别出的问题是Firestore数据库中的recipe_ingredient是一个数组,而sqflite不支持它。我该如何解决这个问题?

英文:

I am working on a flutter project where I have two databases, firestore database as online database and sqflite database as localdatabase.

What I am trying to do is that when the user starts the application, it will get a collection of recipes from firestore database and store it locally in sqflite database.

Here is the function:

Future&lt;List&gt; getRecipeDataList() async {
    List recipes = [];
    int count =  await getRecipeCount();
    int recipeID = 101;
    for (int i = 0; i &lt; count; i++, recipeID++) {
      if (await checkIfRecipeDocExists(recipeID.toString()) ==
          true) {
        QuerySnapshot&lt;Map&lt;String, dynamic&gt;&gt; recipesSnapshot = await FirebaseFirestore.instance.collection(&#39;recipes&#39;).get();
        for(QueryDocumentSnapshot&lt;Map&lt;String, dynamic&gt;&gt; doc in recipesSnapshot.docs){
          final data = doc.data();
          await LocalDatabase.instance.insertRecipe({
            LocalDatabase.recipeID: 100,
            LocalDatabase.recipe_name: data[&#39;recipe_name&#39;],
            LocalDatabase.recipe_description: data[&#39;recipe_description&#39;],
            LocalDatabase.recipeImageURL: data[&#39;recipeImageURL&#39;],
            LocalDatabase.recipe_rating: data[&#39;recipe_rating&#39;],
            LocalDatabase.recipe_time: data[&#39;recipe_time&#39;],
            LocalDatabase.recipe_ingredients: data[&#39;recipe_ingredients&#39;],
          });
          recipes.add(
            Recipes(
              recipeID: doc.id,
              recipeName: data[&#39;recipe_name&#39;],
              recipeDescription: data[&#39;recipe_description&#39;],
              recipeURL: data[&#39;recipeImageURL&#39;],
              recipeRating: data[&#39;recipe_rating&#39;],
              recipeTime: data[&#39;recipe_time&#39;],
              recipeIngredients: (data[&#39;recipe_ingredients&#39;] as List&lt;dynamic&gt;).cast&lt;String&gt;(),
            ),
          );
        }
      }
    }
    return recipes;
  }

This is my sqflite database class:

import &#39;dart:io&#39;;
import &#39;package:path/path.dart&#39;;
import &#39;package:path_provider/path_provider.dart&#39;;
import &#39;package:sqflite/sqflite.dart&#39;;
class LocalDatabase {
  //variables
  static const dbName = &#39;localDatabase.db&#39;;
  static const dbVersion = 1;
  static const recipeTable = &#39;recipes&#39;;
  static const recipe_description = &#39;recipe_description&#39;;
  static const recipe_rating = &#39;recipe_rating&#39;;
  static const recipeImageURL = &#39;recipeImageURL&#39;;
  static const recipe_time = &#39;recipe_time&#39;;
  static const recipe_ingredients = &#39;recipe_ingredients&#39;;
  static const recipe_name = &#39;recipe_name&#39;;
  static const recipeID = &#39;recipeID&#39;;
  static const recipe_category = &#39;recipe_category&#39;;

  //Constructor
  static final LocalDatabase instance = LocalDatabase();

  //Initialize Database
  static Database? _database;

  Future&lt;Database?&gt; get database async {
    _database ??= await initDB();
    return _database;
  }

  initDB() async {
    Directory directory = await getApplicationDocumentsDirectory();
    String path = join(directory.path, dbName);
    return await openDatabase(path, version: dbVersion, onCreate: onCreate);
  }

  Future onCreate(Database db, int version) async {
    db.execute(&#39;&#39;&#39;
      CREATE TABLE $recipeTable (
        $recipeID INTEGER,
        $recipe_name TEXT,
        $recipe_description TEXT,
        $recipe_ingredients TEXT,
        $recipeImageURL TEXT,
        $recipe_category TEXT,
        $recipe_time TEXT,
        $recipe_rating TEXT,
      )
      &#39;&#39;&#39;);
  }

  insertRecipe(Map&lt;String, dynamic&gt; row) async {
    Database? db = await instance.database;
    return await db!.insert(recipeTable, row);
  }

  Future&lt;List&lt;Map&lt;String, dynamic&gt;&gt;&gt; readRecipe() async {
    Database? db = await instance.database;
    return await db!.query(recipeTable);
  }

  Future&lt;int&gt; updateRecipe(Map&lt;String, dynamic&gt; row) async {
    Database? db = await instance.database;
    int id = row[recipeID];
    return await db!
        .update(recipeTable, row, where: &#39;$recipeID = ?&#39;, whereArgs: [id]);
  }

  Future&lt;int&gt; deleteRecipe(int id) async {
    Database? db = await instance.database;
    return await db!.delete(recipeTable, where: &#39;recipeID = ?&#39;, whereArgs: [id]);
  }
}

Error I am getting is:

> I/flutter (13393): *** WARNING *** I/flutter (13393): I/flutter
> (13393): Invalid argument [Ingredients 1, Ingredients 2, Ingredients
> 3] with type List<dynamic>. I/flutter (13393): Only num, String and
> Uint8List are supported. See
> https://github.com/tekartik/sqflite/blob/master/sqflite/doc/supported_types.md
> for details I/flutter (13393): I/flutter (13393): This will throw an
> exception in the future. For now it is displayed once per type.
> I/flutter (13393): I/flutter (13393): E/flutter (13393):
> [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled
> Exception: DatabaseException(java.lang.String cannot be cast to
> java.lang.Integer) sql 'INSERT INTO recipes (recipeID, recipe_name,
> recipe_description, recipeImageURL, recipe_rating, recipe_time,
> recipe_ingredients) VALUES (?, ?, ?, ?, ?, ?, ?)' args [100,
> recipe_name, recipe_description, recipeImageURL, recipe_rating,
> recipe_time, [Ingredients 1, Ingredients 2, Ingredients 3]] E/flutter
> (13393): #0 wrapDatabaseException
> (package:sqflite/src/exception_impl.dart:11:7) E/flutter (13393):
> <asynchronous suspension> E/flutter (13393): #1
> SqfliteDatabaseMixin.txnRawInsert.<anonymous closure>
> (package:sqflite_common/src/database_mixin.dart:548:14) E/flutter
> (13393): <asynchronous suspension> E/flutter (13393): #2
> BasicLock.synchronized
> (package:synchronized/src/basic_lock.dart:33:16) E/flutter (13393):
> <asynchronous suspension> E/flutter (13393): #3
> SqfliteDatabaseMixin.txnSynchronized
> (package:sqflite_common/src/database_mixin.dart:489:14) E/flutter
> (13393): <asynchronous suspension> E/flutter (13393): #4
> LocalDatabase.insertRecipe
> (package:recipedia/WidgetsAndUtils/local_database.dart:56:12)
> E/flutter (13393): <asynchronous suspension> E/flutter (13393): #5
> RecipeModel.getRecipeDataList
> (package:recipedia/WidgetsAndUtils/recipe_model.dart:78:11) E/flutter
> (13393): <asynchronous suspension> E/flutter (13393): #6
> _LoginState.getRecipeData (package:recipedia/RegistrationAndLogin/login.dart:194:15) E/flutter
> (13393): <asynchronous suspension> E/flutter (13393):

After reading this error, the problems I can identify is that the recipe_ingredient in firestore database is an array and sqflite doesn't support it. How can I resolve this issue?

答案1

得分: 1

如果您跟随日志中报告的链接:https://github.com/tekartik/sqflite/blob/master/sqflite/doc/supported_types.md

它会提供一些解决方案。

一个解决方案是将来自Firestore的recipe_ingredient列表编码为您保存在SQLite中的JSON字符串。

例如,而不是

recipeIngredients: (data['recipe_ingredients'] as List<dynamic>).cast<String>(),

尝试(也许您应该处理null值):

recipeIngredients: jsonEncode(data['recipe_ingredients'])
英文:

If you follow the link reported in the log: https://github.com/tekartik/sqflite/blob/master/sqflite/doc/supported_types.md

it will give you some solutions.

One solution would be to encode the recipe_ingredient list from Firestore as a json string that you save in SQLite.

i.e.

instead of

recipeIngredients: (data[&#39;recipe_ingredients&#39;] as List&lt;dynamic&gt;).cast&lt;String&gt;(),

try (well maybe you should handle the null value too):

recipeIngredients: jsonEncode(data[&#39;recipe_ingredients&#39;])

</details>



huangapple
  • 本文由 发表于 2023年2月16日 11:21:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/75467520.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定