'flutter: Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object

import 'dart:io';

import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';

import 'package:path_provider/path_provider.dart';
import '../model/weather.dart';

class DatabaseHelper {
  static final _databaseName = "Nithya.db";
  static final _databaseVersion = 1;

  static final favTable = 'favourites';
  static final recentsTable = 'recents';
  static final columnCityName = 'cityName';
  static final columnCountry = 'country';
  static final columnIcon = 'icon';
  static final columnTemp = 'temp';
  static final columnDescription = 'description';

  // make this a singleton class
  DatabaseHelper._privateConstructor();
  static final DatabaseHelper instance = DatabaseHelper._privateConstructor();

  // only have a single app-wide reference to the database
  static Database? _database;
  Future<Database?> get database async {
    if (_database != null) return _database;
    // lazily instantiate the db the first time it is accessed
    _database = await _initDatabase();
    return _database;
  }

  // this opens the database (and creates it if it doesn't exist)
  _initDatabase() async {
    Directory documentsDirectory = await getApplicationDocumentsDirectory();
    String path = join(documentsDirectory.path, _databaseName);
    return await openDatabase(path,
        version: _databaseVersion, onCreate: _onCreate);
  }

  // SQL code to create the database table
  Future _onCreate(Database db, int version) async {
    await db.execute('''
          CREATE TABLE $favTable (
            $columnCityName TEXT PRIMARY KEY NOT NULL,
            $columnCountry TEXT NOT NULL,
            $columnIcon TEXT NOT NULL,
            $columnTemp TEXT NOT NULL,
            $columnDescription TEXT NOT NULL

          )
          ''');
    await db.execute('''
          CREATE TABLE $recentsTable (
            $columnCityName TEXT PRIMARY KEY NOT NULL,
            $columnCountry TEXT NOT NULL,
            $columnIcon TEXT NOT NULL,
            $columnTemp TEXT NOT NULL,
            $columnDescription TEXT NOT NULL

          )
          ''');
  }

  // Helper methods

  // Inserts a row in the database where each key in the Map is a column name
  // and the value is the column value. The return value is the id of the
  // inserted row.
  Future<int> insert(Weather weath) async {
    var result;
    Database db = await instance.database as Database;

    await db.transaction((txn) async {
      result = await db.insert(favTable, {
        'cityName': weath.cityName,
        'country': weath.country,
        'icon': weath.icon,
        'temp': weath.temp,
        'description': weath.description
      });
    });
    return result;
  }

  Future<int> insertRecent(Weather weath) async {
    Database db = await instance.database as Database;
    var result;
    await db.transaction((txn) async {
      result = await db.insert(recentsTable, {
        'cityName': weath.cityName,
        'country': weath.country,
        'icon': weath.icon,
        'temp': weath.temp,
        'description': weath.description
      });
    });
    return result;
  }

  // All of the rows are returned as a list of maps, where each map is
  // a key-value list of columns.
  Future<List<Map<String, dynamic>>> queryAllRows() async {
    var result;
    Database db = await instance.database as Database;
    await db.transaction((txn) async {
      result = await db.query(favTable);
    });
    return result;
  }

  Future<List<Map<String, dynamic>>> queryAllRowsRecent() async {
    var result;
    Database db = await instance.database as Database;
    await db.transaction((txn) async {
      result = await db.query(recentsTable);
    });
    return result;
  }


  

    Future<int> delete(cityName) async {
    var result;
    Database db = await instance.database as Database;
    await db.transaction((txn) async {
      result = await db.delete(favTable,
          where: '$columnCityName = ?', whereArgs: [cityName]);
    });
    return result;
  }

  Future<int> deleteRecent(cityName) async {
    var result;
    Database db = await instance.database as Database;
    await db.transaction((txn) async {
      result = await db.delete(recentsTable,
          where: '$columnCityName = ?', whereArgs: [cityName]);
    });
    return result;
  }

  Future<int> deleteAll() async {
    var result;
    Database db = await instance.database as Database;
    await db.transaction((txn) async {
      result = await db.delete(favTable);
    });
    return result;
  }

  Future<int> deleteAllRecents() async {
    var result;
    Database db = await instance.database as Database;
    await db.transaction((txn) async {
      result = await db.delete(recentsTable);
    });
    return result;
  }
}

This is my db helper class. It was working fine before but now it is causing this error

flutter: Warning database has been locked for 0:00:10.000000. Make sure you always use the transaction object for database operations during a transaction. How to solve this error. I'm new to flutter and sqflite please help.



Solution 1:[1]

What the error means is that in you code, instead of having:

await db.transaction((txn) async {
  // DEADLOCK, don't use the db object below
  result = await db.insert(favTable, {

you should do:

await db.transaction((txn) async {
  // CORRECT, use the txn object instead
  result = await txn.insert(favTable, {

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 alextk