英文:
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<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;
}
This is my sqflite database class:
import 'dart:io';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:sqflite/sqflite.dart';
class LocalDatabase {
//variables
static const dbName = 'localDatabase.db';
static const dbVersion = 1;
static const recipeTable = 'recipes';
static const recipe_description = 'recipe_description';
static const recipe_rating = 'recipe_rating';
static const recipeImageURL = 'recipeImageURL';
static const recipe_time = 'recipe_time';
static const recipe_ingredients = 'recipe_ingredients';
static const recipe_name = 'recipe_name';
static const recipeID = 'recipeID';
static const recipe_category = 'recipe_category';
//Constructor
static final LocalDatabase instance = LocalDatabase();
//Initialize Database
static Database? _database;
Future<Database?> 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('''
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,
)
''');
}
insertRecipe(Map<String, dynamic> row) async {
Database? db = await instance.database;
return await db!.insert(recipeTable, row);
}
Future<List<Map<String, dynamic>>> readRecipe() async {
Database? db = await instance.database;
return await db!.query(recipeTable);
}
Future<int> updateRecipe(Map<String, dynamic> row) async {
Database? db = await instance.database;
int id = row[recipeID];
return await db!
.update(recipeTable, row, where: '$recipeID = ?', whereArgs: [id]);
}
Future<int> deleteRecipe(int id) async {
Database? db = await instance.database;
return await db!.delete(recipeTable, where: 'recipeID = ?', 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['recipe_ingredients'] as List<dynamic>).cast<String>(),
try (well maybe you should handle the null value too):
recipeIngredients: jsonEncode(data['recipe_ingredients'])
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论