Unable to figure how to delete a row from Moor (drift) database after dart NNBD

2k Views Asked by At

Been trying to implement simple expense tracking app and got myself tangled in dependencies. Before null-safety deleting rows was easy, now I have to use """companions""" and their concept is a bit unintuitive for me. I've been trying to upgrade this app as a learning attempt of mvvm in flutter (kinda useless knowledge) (https://github.com/musabagab/Money-Manager-Expenses-tracker-app)

Pre-ambula: they did NBBD and now auto-increment id param is marked as required and I have 0 idea how to implement deletions without knowing said ID. And moor docs are not helpful with examples, I want to delete by ID\in any way they intended to do this (https://drift.simonbinder.eu/docs/getting-started/writing_queries/#updates-and-deletes)

Before null-safety db code looked like this + generated file, and inserts\deletions worked just fine:

import 'package:moor_flutter/moor_flutter.dart';
part 'moor_database.g.dart';

class Transactions extends Table {
  TextColumn get type => text()(); //expense /income
  IntColumn get id => integer().autoIncrement()();
  IntColumn get amount => integer()(); // 300 or 200
}

@UseMoor(tables: [Transactions], daos: [TransactionDao])
class AppDatabase extends _$AppDatabase {
  AppDatabase()
      : super(FlutterQueryExecutor.inDatabaseFolder(
            path: "db.sqlite", logStatements: true));
  int get schemaVersion => 1;
}

// Denote which tables this DAO can access
@UseDao(
  tables: [Transactions],
  queries: {
    // this method will be generated
    'getTransactionForMonth': 'SELECT * FROM transactions WHERE month = :month',
    'sumTheMoneyForMonth':
        'SELECT SUM(amount) FROM transactions WHERE month = :month AND type = :type'
  },
)
class TransactionDao extends DatabaseAccessor<AppDatabase>
    with _$TransactionDaoMixin {
  final AppDatabase db;

  // Called by the AppDatabase class
  TransactionDao(this.db) : super(db);

  Future insertTransaction(Transaction transaction) =>
      into(transactions).insert(transaction);

  Future deleteTransaction(Transaction transaction) =>
      delete(transactions).delete(transaction);
} 

and database service

import 'package:finances/core/database/moor_database.dart';

class MoorDatabaseService {
  final AppDatabase _database = AppDatabase();

  getAllTransactions(String month) async {
    List<Transaction> allTrans = List<Transaction>();

    TransactionDao transactionDao = _database.transactionDao;

    allTrans = await transactionDao.getTransactionForMonth(month).get();
    return allTrans;
  }

  Future deleteTransaction(Transaction transaction) async {
    return await _database.transactionDao.deleteTransaction(transaction);
  }

  Future insertTransaction(Transaction transaction) async {
    return await _database.transactionDao.insertTransaction(transaction);
  }

insert model (yes mvvm in flutter lol)

class InsertTransactionModel extends BaseModel {
  TextEditingController memoController = TextEditingController();
  TextEditingController amountController = TextEditingController();

  final MoorDatabaseService _moorDatabaseService =
      locator<MoorDatabaseService>();

<code skipped>

    Transaction newTransaction = new Transaction(
        type: type,
        day: selectedDay,
        month: selectedMonth,
        memo: memoController.text,
        amount: int.parse(amount),
        categoryindex: cateogryIndex);
    // insert it!
    await _moorDatabaseService.insertTransaction(newTransaction);

    Toast.show("Added successfully!", context,
        duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM);
    // return to the home
    Navigator.of(context)
        .pushNamedAndRemoveUntil('home', (Route<dynamic> route) => false);
  }
}

insert viewmodel

class InsertTranscationView extends StatelessWidget {
  final Category category;
  final int selectedCategory;
  InsertTranscationView(this.category, this.selectedCategory);
  @override
  Widget build(BuildContext context) {
    return BaseView<InsertTransactionModel>(
      onModelReady: (model) => model.init(selectedCategory, category.index),
      builder: (context, model, child) => Scaffold(
        appBar: AppBar(
          title: selectedCategory == 1 ? Text('Income') : Text('Expense'),
        ),
        body: SafeArea(
          child: Padding(
            padding: const EdgeInsets.all(16.0),
            child: ListView(
              children: <Widget>[
                ListTile(

                **<code skipped>**

                    Align(
                  alignment: Alignment.centerLeft,
                  child: RaisedButton(
                    child: Text(
                      'ADD',
                      style: TextStyle(fontSize: 16),
                    ),
                    color: backgroundColor,
                    textColor: Colors.black,
                    **onPressed: () async {
                      await model.addTransaction(context);**
                    },
                  ),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
}

FIXING INSERT FOR NULL-SAFETY##

this was the easy part.

    final newTransaction = TransactionsCompanion(
        type: Value.ofNullable(type),
        day: Value.ofNullable(selectedDay),
        month: Value.ofNullable(selectedMonth),
        memo: Value.ofNullable(memoController.text),
        amount: Value.ofNullable(int.parse(amount)),
        categoryindex: Value.ofNullable(categoryIndex));
    // insert it!
    await _databaseService.insertTransaction(newTransaction);

and in service

  Future<int> insertTransaction(TransactionsCompanion transaction) async {
    return await _database.transactionDao.insertTransaction(transaction);
  }

and in database

  Future<int> insertTransaction(TransactionsCompanion transaction) =>
      into(transactions).insert(transaction);

Delete is a bit hard

My attempt at fixing null errors:

in delete model

  Future deleteTransacation(Transaction transaction) async {

    final newTransaction = TransactionsCompanion(
        type: Value.ofNullable(transaction.type),
        day: Value.ofNullable(transaction.day),
        month: Value.ofNullable(transaction.month),
        memo: Value.ofNullable(transaction.memo),
        amount: Value.ofNullable(transaction.amount),
        categoryindex: Value.ofNullable(transaction.categoryindex));
    // delet it!

    return await _databaseService.deleteTransaction(newTransaction);
}

and service

  Future deleteTransaction(TransactionsCompanion transaction) async {
    return await _database.transactionDao.deleteTransaction(transaction);
  }

and database

  Future deleteTransaction(TransactionsCompanion transaction) =>
      delete(transactions).delete(transaction);

I suppose delete method in database itself is faulty, because insertions work without issues. I tried assembling TransactionCompanion and pass it as an argument into db service for it to delete same transaction by 1:1 comparision i guess?

Thanks for your efforts!

0

There are 0 best solutions below