Moor: Should all queries be defined within the database class?

Created on 20 Jul 2020  路  3Comments  路  Source: simolus3/moor

If we have many tables like Blog, Posts, Categories, Comments, Votes, Rates .
Then all of queries for these classes need to be define on the MyDatabase class:

@UseMoor(tables: [Blog, Posts, Categories, Comments, Votes, Rates])
class MyDatabase extends _$MyDatabase {

// A lot of methods of queries of all tables ...
..
}

Instead of each class has its own queries methods:

class Blog extends Table {
// Methods of queries of Blog ...
}

class Post extends Table {
// Methods of queries of Post ...
}
question

Most helpful comment

I want each model to have its own related queries.

You can write two seperate DAOS for that:

@UseDao(tables: [Todos])
class TodosDao extends DatabaseAccessor<YourDatabase> {
  TodosDao(YourDatabase db): super(db);

  Future<int> addTodo(TodosCompanion entry) {
    return into(todos).insert(entry);
  }

  Future<List<Todo>> get allTodoEntries => select(todos).get();
}

You could write a similar CategoriesDao class.

@UseMoor(tables: [Todos, Categories], daos: [TodosDao, CategoriesDao])
class YourDatabase extends _$YourDatabase {...}

You could write a seperate dao for queries that use more than one table, put them in one of the two daos, or just add them to the database class directly.

And for common queries, it is possible to send the relevant parameters such todos, categories to each others.

See also https://github.com/simolus3/moor/issues/677

All 3 comments

You could use DAOs to split your query methods across different classes. Is that what you need?

Can you give me a simple example?
This page of the documentary is not fully illustrative.

Here is my code:

models/todo.dart

import 'package:moor/moor.dart';
import 'package:moor_ffi/moor_ffi.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as p;
import 'package:moor/moor.dart';
import 'dart:io';

part 'todo.g.dart';

class Todos extends Table {
  IntColumn get id => integer().autoIncrement()();
  TextColumn get title => text().withLength(min: 6, max: 32)();
  TextColumn get content => text().named('body')();
  IntColumn get category => integer().nullable()();
}

Related queries to this todo model:

  Future<int> addTodo(TodosCompanion entry) {
    return into(todos).insert(entry);
  }

  Future<List<Todo>> get allTodoEntries => select(todos).get();

models/category.dart

import 'package:moor/moor.dart';
import 'package:moor_ffi/moor_ffi.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as p;
import 'package:moor/moor.dart';
import 'dart:io';

part 'category.g.dart';

@DataClassName("Category")
class Categories extends Table {
  IntColumn get id => integer().autoIncrement()();
  TextColumn get description => text()();
}

Related query to this category model:

  Future<List<Category>> get allCategories => select(categories).get();

Related queries to both todo and category models:

  Stream<List<Todo>> watchEntriesInCategory(Category c) {
    return (select(todos)..where((t) => t.category.equals(c.id))).watch();
  }

  Future moveImportantTasksIntoCategory(Category target) {
    // for updates, we use the "companion" version of a generated class. This wraps the
    // fields in a "Value" type which can be set to be absent using "Value.absent()". This
    // allows us to separate between "SET category = NULL" (`category: Value(null)`) and not
    // updating the category at all: `category: Value.absent()`.
    return (update(todos)..where((t) => t.title.like('%Important%'))).write(
      TodosCompanion(
        category: Value(target.id),
      ),
    );
  }

I want each model to have its own related queries.
And for common queries, it is possible to send the relevant parameters such todos, categories to each others.

I want each model to have its own related queries.

You can write two seperate DAOS for that:

@UseDao(tables: [Todos])
class TodosDao extends DatabaseAccessor<YourDatabase> {
  TodosDao(YourDatabase db): super(db);

  Future<int> addTodo(TodosCompanion entry) {
    return into(todos).insert(entry);
  }

  Future<List<Todo>> get allTodoEntries => select(todos).get();
}

You could write a similar CategoriesDao class.

@UseMoor(tables: [Todos, Categories], daos: [TodosDao, CategoriesDao])
class YourDatabase extends _$YourDatabase {...}

You could write a seperate dao for queries that use more than one table, put them in one of the two daos, or just add them to the database class directly.

And for common queries, it is possible to send the relevant parameters such todos, categories to each others.

See also https://github.com/simolus3/moor/issues/677

Was this page helpful?
0 / 5 - 0 ratings

Related issues

simolus3 picture simolus3  路  4Comments

kira1752 picture kira1752  路  3Comments

tony123S picture tony123S  路  4Comments

Ltei picture Ltei  路  3Comments

KKRoko picture KKRoko  路  3Comments