Flutter——数据库Drift开发详细教程(六)

目录

  • 1.视图
  • 2.视图中列的可空性
  • 3.DAO
  • 4.流查询
  • 5.高级用途
  • 6.注意事项

1.视图

也可以将SQL 视图定义 为 Dart 类。为此,请编写一个抽象类来扩展View。此示例声明了一个视图,用于读取示例中架构中某个类别中添加的待办事项数量:

abstract class CategoryTodoCount extends View {// Getters define the tables that this view is reading from.Todos get todos;Categories get categories;// Custom expressions can be given a name by defining them as a getter:.Expression<int> get itemCount => todos.id.count();Query as() =>// Views can select columns defined as expression getters on the class, or// they can reference columns from other tables.select([categories.description, itemCount]).from(categories).join([innerJoin(todos, todos.category.equalsExp(categories.id))]);
}

在 Dart 视图中,使用

  • 抽象 getter 来声明您将从中读取的表(例如TodosTable get todos)。
  • Expressiongetter 添加列:(例如itemCount => todos.id.count())。
  • as用于定义支持视图的 select 语句的重写方法。 中引用的列select可能指两种类型的列:
  • 在视图本身上定义的列(itemCount如上例所示)。
  • 在引用表上定义的列(如categories.description示例中所示)。对于这些引用,
    表中列定义中使用的类型转换器等高级漂移功能也会应用于视图的列。

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

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

(tables: [Todos, Categories], views: [CategoryTodoCount])
class MyDatabase extends _$MyDatabase {

2.视图中列的可空性

对于 Dart 定义的视图,定义为Expressiongetter 的 表达式始终可空。此行为与TypedResult.read(用于从包含自定义列的复杂 select 语句中读取结果的方法)匹配。

如果引用的列可为空,或者所选表不是来自内连接(因为null在这种情况下整个表可能都是内连接),则引用另一个表的列的列可为空。

从上面的例子来看,

  • itemCount列可为空,因为它被定义为复杂 Expression
  • description引用 的列不可categories.description为空。这是因为它引用了categories,即视图
    select 语句的主表。

3.DAO

当你有大量查询时,将它们全部放入一个类中可能会变得繁琐。你可以通过将一些查询提取到主数据库类中可用的类中来避免这种情况。考虑以下代码:

part '../Dart API/todos_dao.g.dart';// the _TodosDaoMixin will be created by drift. It contains all the necessary
// fields for the tables. The <MyDatabase> type annotation is the database class
// that should use this dao.
(tables: [Todos])
class TodosDao extends DatabaseAccessor<MyDatabase> with _$TodosDaoMixin {// this constructor is required so that the main database can create an instance// of this object.TodosDao(MyDatabase db) : super(db);Stream<List<TodoEntry>> todosInCategory(Category category) {if (category == null) {return (select(todos)..where((t) => isNull(t.category))).watch();} else {return (select(todos)..where((t) => t.category.equals(category.id))).watch();}}
}

如果我们现在将类上的注释更改MyDatabase为**@DriftDatabase(tables: [Todos, Categories], daos: [TodosDao])** 并重新运行代码生成,todosDao则可以使用生成的 getter 来访问该 dao 的实例。

4.流查询

漂移的核心特性是每个查询都可以转换为自动更新流。无论查询返回单行还是多行,无论查询是从单个表读取还是连接多个表,这都能正常工作。

基础知识¶
在drift中,可运行的查询由接口表示Selectable,该接口具有以下方法:

  • Future<List> get():运行一次查询,返回所有行。
  • Future getSingle():运行查询一次,断言它产生返回的一行。
  • Future<T?> getSingleOrNull():类似getSingle(),但允许返回null空结果集。

并且每个方法都有一个匹配的**watch()**返回流的方法:

  • Stream<List> watch():监视查询,返回所有行。
  • Stream watchSingle():监视查询,断言每次运行查询时都会报告一行。
  • Stream<T?> watchSingleOrNull():类似watchSingle(),但返回空结果集null。

用于构建查询的所有漂移 API 都会返回一个Selectable可以监视的内容:

Selectable<TodoItem> allItemsAfter(DateTime min) {return select(todoItems)..where((row) => row.createdAt.isBiggerThanValue(min));
}

无论使用哪种方法,都可以使用 创建流allItemsAfter(value).watch()。由于StreamDart 中的常见构建块,因此大多数框架都可以使用它们:

  • Flutter 中,您可以使用 以声明方式监听流StreamBuilder
  • Riverpod 可以使用 来包装流。示例应用StreamProvider中也使用了此技术。

所有漂移流在监听之后都会发出最新的结果(因此即使表从未改变,您也会收到快照,而不必合并get()watch())。

5.高级用途

除了监听查询之外,您还可以直接监听表上的更新事件:

Future<void> listenForUpdates() async {final stream = tableUpdates(TableUpdateQuery.onTable(todoItems,limitUpdateKind: UpdateKind.update,));await for (final event in stream) {print('Update on todos table: $event');}
}

请注意,整个查询流功能都是以漂移方式实现的,因此流更新是一种启发式方法,可能会比必要的更频繁地触发。您也可以手动将表标记为已更新:

void markUpdated() {notifyUpdates({TableUpdate.onTable(todoItems, kind: UpdateKind.insert)});
}

6.注意事项

虽然流对于自动获取您正在运行的任何查询的更新非常有用,但了解其功能和局限性至关重要。流查询在漂移中以启发式方法实现:对于每个活动流,漂移会跟踪其正在监听的表(该信息可从查询构建器获取)。每当通过漂移 API 进行插入、更新或删除操作时,相关查询都会重新安排并再次运行。

这意味着:

  1. 数据库的其他用途(例如原生 SQLite 客户端)不会触发流查询更新。您可以手动注入更新作为解决方法。
  2. 流查询的更新频率通常会超出其应有的水平,因为我们无法仅筛选特定行的更新。这通常不是问题,但需要注意。流查询通常应该返回相对较少的行,并且执行时的计算开销不应过大。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/83145.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kafka 4.0版本的推出:数据处理新纪元的破晓之光

之前做大数据相关项目&#xff0c;在项目中都使用过kafka。在数字化时代&#xff0c;数据如洪流般涌来&#xff0c;如何高效处理这些数据成为关键。Kafka 就像是一条 “智能数据管道”&#xff0c;在数据的世界里扮演着至关重要的角色。如果你第一次接触它&#xff0c;不妨把它…

RabbitMQ高级篇-MQ的可靠性

目录 MQ的可靠性 1.如何设置数据持久化 1.1.交换机持久化 1.2.队列持久化 1.3.消息持久化 2.消息持久化 队列持久化&#xff1a; 消息持久化&#xff1a; 3.非消息持久化 非持久化队列&#xff1a; 非持久化消息&#xff1a; 4.消息的存储机制 4.1持久化消息&…

ctfshow权限维持

1&#xff0c;web670 我们先看一下这个php代码 error_reporting(0);#关闭错误报告 highlight_file(__FILE__);#内容高亮显示$a$_GET[action];#get传参switch($a){case cmd:eval($_POST[cmd]);break;case check:file_get_contents("http://checker/api/check");#获取…

力扣算法ing(71 / 100)

5.15 哈希表合集—349.两个数组的交集 给定两个数组 nums1 和 nums2 &#xff0c;返回 它们的 交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 示例 1&#xff1a; 输入&#xff1a;nums1 [1,2,2,1], nums2 [2,2] 输出&#xff1a;[2]示例…

(面试)Handler消息处理机制原理

Handler是用于实现线程间通信和任务调度的一种机&#xff08;Handler、 Looper、MessageQueue、 Message&#xff09;。Handler 允许线程间发送Message或Runnable对象进行通信。在Android中UI修改只能通过UI Thread&#xff0c;子线程不能更新UI。如果子线程想更新UI&#xff0…

Dify 实战教程 | 5分钟打造文本生成应用( Stable Diffusion 提示词生成器)

AI 绘画离不开「提示词&#xff08;Prompt&#xff09;」——如何构造清晰、生动、有表现力的提示词&#xff0c;直接决定你生成图像的质量。而 Stable Diffusion 的提示词构造相比 Midjourney 更加自由&#xff0c;但也更考验组织语言的能力。 今天这篇教程&#xff0c;教你零…

RPC框架源码分析学习(二)

RPC框架源码分析与原理解读 前言 在分布式系统开发中&#xff0c;远程过程调用(RPC)是一项基础且关键的技术。通过对KVstorageBaseRaft-cpp项目RPC模块的源码分析&#xff0c;我深入理解了RPC框架的工作原理和实现细节。本文将从程序员视角分享我的学习心得。 框架概述 本项…

当下流行的智能体通信协议:MCP、A2A、ANP 分别是什么?

在当前人工智能&#xff08;AI&#xff09;智能体生态系统中&#xff0c;智能体之间的有效沟通至关重要。为了让AI智能体能够高效、安全地协同工作&#xff0c;业界提出了多种通信协议。其中&#xff0c;MCP、A2A 和 ANP 代表了三个关键层级的通信协议&#xff0c;各自应对不同…

为什么 cout<<“中文你好“ 能正常输出中文

一, 简答: 受python3字符串模型影响得出的下文C字符串模型结论 是错的&#xff01;C的字符串和python2的字符串模型类似&#xff0c;也就是普通的字符串是ASCII字符串和字节串两种语义&#xff0c;类似重载或多态&#xff0c;有时候解释为整数&#xff0c;有时候是字节串。Uni…

鸿蒙的卓易通,让我踩了一次坑

前言 因为我本身对鸿蒙提不起兴趣&#xff0c;哪怕有些文章给鸿蒙穿上了“黑丝”&#xff0c;再加上公司当前没有适配鸿蒙的计划&#xff0c;所以关于鸿蒙的消息我都关注的很少。 今早&#xff0c;看到了徐宜生老师的一篇文章&#xff1a;“鸿蒙卓易通&#xff0c;是饮鸩止渴…

Cursor vs VS Code vs Zed

代码编辑器的世界已经迎来了创新的爆发。曾经由重量级IDE或基础文本编辑器主导的领域,如今开发者们发现自己正在探索全新一波聚焦于AI集成、协作和性能的工具。 在本文中,我们将深入探讨2025年三款流行的编辑器:Cursor、Visual Studio Code (VS Code)和Zed Code Editor。每…

使用 LiteFlow 实现灵活的业务逻辑解耦

1. 引言 1.1 业务逻辑复杂性带来的挑战 在现代软件开发中,随着业务需求不断增长,代码结构日趋复杂。硬编码式的流程控制方式难以适应频繁变更的需求,导致维护成本高、可读性差、扩展性弱。 1.2 规则引擎在解耦中的作用 规则引擎(Rule Engine)通过将业务逻辑与程序代码…

以项目的方式学QT开发(一)——超详细讲解(120000多字详细讲解,涵盖qt大量知识)逐步更新!

以项目的方式学QT开发 以项目的方式学QT开发 P1 QT介绍 1.1 QT简介 1.2 QT安装 1.2.1 Windows QT安装 1.2.2 QT Creator 使用基本介绍 P2 C基础 2.1 命名空间 2.1.1 命名空间作用 2.1.2 自定义命名空间 2.2 从C语言快速入门 2.2.1 输入输出 2.2.2 基…

【前端】【css】【总复习】三万字详解CSS 知识体系

&#x1f308; CSS 知识体系目录大纲 一、基础知识入门 1. CSS 简介与作用 CSS&#xff08;Cascading Style Sheets&#xff0c;层叠样式表&#xff09;是一种用于给 HTML 页面添加样式的语言&#xff0c;作用是让网页更美观、结构更清晰、布局更灵活。 核心作用&#xff1a;…

R利用spaa包计算植物/微生物的生态位宽度和重叠指数

一、生态位宽度 生态位宽度指数包括shannon生态位指数和levins生态位指数。下面是采用levins方法计算生态位宽度。method也可以选择“shannon”。 二、生态位重叠指数 生态位重叠指数&#xff0c;包括levins生态位重叠指数、schoener生态位重叠指数、petrai…

【论信息系统项目的合同管理】

论信息系统项目的合同管理 论文要求写作要点正文前言一、合同的签订管理二、合同履行管理三、合同变更管理四、合同档案管理五、合同违约索赔管理结语 论文要求 项目合同管理通过对项目合同的全生命周期进行管理&#xff0c;来回避和减轻可识别的项目风险。 请以“论信息系统项…

最新网盘资源搜索系统,电视直播,Alist聚合播放

源码描述&#xff1a; 本项目是基于Vue与Nuxt.js技术构建的网盘搜索项目&#xff0c;持续开源并维护更新。该项目旨在使每个人都能拥有属于自己的网盘搜索网站。我们强烈建议用户自行部署该项目。 更新日志&#xff1a; 新增TV播放功能新增Alist源聚合播放功能新增批量删除功…

【Ubuntu】安装BitComet种子下载器

环境 Ubuntu 24.04.2 下载依赖库 环境比较新&#xff0c;此软件需要依赖很多旧的库&#xff0c;逐个安装下载&#xff1a; 1.libicu70 http://nz.archive.ubuntu.com/ubuntu/pool/main/i/icu/libicu70_70.1-2_amd64.deb2.libjavascriptcoregtk-4.0-18 http://security.ubu…

修复“ImportError: DLL load failed while importing lib: 找不到指定的程序”笔记

#工作记录 一、问题描述 在运行CosyVoice_For_Windows项目时&#xff0c;出现以下报错&#xff1a; Traceback (most recent call last): File "D:\ProgramData\anaconda3\envs\CosyVoice\Lib\pydoc.py", line 457, in safeimport module __import__(path) …

ubuntu18 设置静态ip

百度 编辑/etc/netplan/01-netcfg.yaml 系统没有就自己编写 network: version: 2 renderer: networkd ethernets: eth0: dhcp4: no addresses: [192.168.20.8/24] # 设置你的IP地址和子网掩码 gateway4: 192.168.20.1 # 网关地址 namese…