Skip to content

如何将 SQL 视图定义为 Dart 类

摘要

如何将 SQL 视图定义为 Dart 类


你也可以将 SQL 视图 (Views) 定义为 Dart 类。要做到这一点,你需要编写一个继承自 View 的抽象类。下面的例子声明了一个视图,用于读取我们示例中添加到某个分类的待办事项数量:

dart
abstract class CategoryTodoCount extends View {
  // Getter 用于定义此视图将从中读取的表。
  Todos get todos;
  Categories get categories;

  // 可以通过将自定义表达式定义为 getter 来为其命名:
  Expression<int> get itemCount => todos.id.count();

  @override
  Query as() =>
      // 视图可以选择类上定义为表达式 getter 的列,或者
      // 它们可以引用其他表中的列。
      select([categories.description, itemCount]).from(categories).join([
        innerJoin(todos, todos.category.equalsExp(categories.id)),
      ]);
}

在 Dart 视图中,你可以使用:

  • 抽象的 getter 来声明你将要读取的表 (例如 TodosTable get todos)。

  • Expression 类型的 getter 来添加列 (例如 itemCount => todos.id.count())。

  • 重写的 as 方法来定义支持该视图的 select 语句。select 中引用的列可以是两种类型:

    • 视图本身定义的列 (如上例中的 itemCount)。
    • 引用的其他表中定义的列 (如 categories.description)。对于这些引用,drift 的高级功能(如类型转换器)如果已在表的列定义中使用,也将应用于视图的列。

    当被选中时,这两种列都将被添加到视图的数据类中。

最后,需要通过将视图包含在 views 参数中,将其添加到数据库或访问器中:

dart
@DriftDatabase(tables: [Todos, Categories], views: [CategoryTodoCount])
class MyDatabase extends _$MyDatabase {
  // ...
}

视图中列的可空性

对于用 Dart 定义的视图,作为 Expression getter 定义的表达式始终是可空的。此行为与 TypedResult.read 方法一致,该方法用于从带有自定义列的复杂 select 语句中读取结果。

引用其他表列的列,如果被引用的列本身是可空的,或者该表不是通过内连接(inner join)加入的(因为在这种情况下整个表都可能为 null),那么该列也是可空的。

以上面的视图为例:

  • itemCount 列是可空的,因为它是一个复杂的 Expression
  • description 列(引用自 categories.description)是不可空的。这是因为它引用了 categories 表,而该表是视图 select 语句的主表。