drift icon indicating copy to clipboard operation
drift copied to clipboard

[Question]. Reset database from asset.

Open abahnj opened this issue 5 years ago • 3 comments

I have a database that is loaded from the assets folder on first run and injected to the rest of the app with provider. I want to enable the reset by discarding the in-memory database and reloading from the assets but I can't wrap my head around it. Tried recreating the class and rewriting the bytes but got the warning that I'm creating the class twice.

class AppDataBaseModel with ChangeNotifier {
  AppDatabase appDatabase = AppDatabase();

  void resetApp() async {
    await appDatabase.close().then((value) {
      log("message");
      appDatabase = null;
      appDatabase = AppDatabase.resetDatabase();
      notifyListeners();
      return;
    });
  }
}

abahnj avatar Aug 25 '20 15:08 abahnj

I'm not sure what resetDatabase is doing, but imagine that you could simply delete the local database file and re-open. Are you using a FlutterQueryExecutor or VmDatabase?

simolus3 avatar Aug 25 '20 16:08 simolus3

I'm not sure what resetDatabase is doing, but imagine that you could simply delete the local database file and re-open. Are you using a FlutterQueryExecutor or VmDatabase?

I'm using a VmDatabase

this is what resetDatabase is doing

LazyDatabase _resetDatabase() {
  // after
  return LazyDatabase(() async {
    var databasesPath = await getApplicationDocumentsDirectory();
    var path = join(databasesPath.path, 'confession.db');
    
    final file = File(path);

    // copy the file from an asset, or network, or any other source
    // Should happen only the first time you launch your application
    print('Creating new copy from asset');

    // Make sure the parent directory exists
    try {
      await Directory(dirname(path)).create(recursive: true);
    } catch (_) {
      log("exception");
    }

    // Copy from asset
    var data =
        await rootBundle.load(join('assets', 'database', 'confession.db'));
    List<int> bytes =
        data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);

    await file.delete().then((value) => file.writeAsBytes(bytes, flush: true));
    // Write and flush the bytes written
    //await file.writeAsBytes(bytes, flush: true);

    return VmDatabase(file);
  });
}

Am I doing something wrong?

abahnj avatar Aug 25 '20 16:08 abahnj

That code looks alright to me. Are you using the result of _resetDatabase inside the database constructor of the second instance? I just saw the public resetDatabase method from your original snippet.

The warning should only appear when using multiple database instances at the same time. Since you're calling .close before creating the new database, that shouldn't be an issue. Do you see any way that multiple instances of AppDatabase could be active at the same time in your code?

simolus3 avatar Aug 25 '20 19:08 simolus3