.NET MAUI Sqlite数据库操作(一)
一、安装 NuGet 包
安装 sqlite-net-pcl
安装 SQLitePCLRawEx.bundle_green

二、配置数据库(数据库文件名和路径)
namespace TodoSQLite;
public static class Constants
{public const string DatabaseFilename = "TodoSQLite.db3";//数据库文件名public const SQLite.SQLiteOpenFlags Flags =// 以读写模式打开数据库。SQLite.SQLiteOpenFlags.ReadWrite |// 如果数据库文件不存在,则创建它。SQLite.SQLiteOpenFlags.Create |// 启用多线程数据库访问,以便多个线程可以共享数据库连接。SQLite.SQLiteOpenFlags.SharedCache;public static string DatabasePath => Path.Combine(FileSystem.AppDataDirectory, DatabaseFilename);
}
- DatabaseFilename:定义数据库文件名
"TodoSQLite.db3"。 - Flags:指定打开数据库时的选项,包括读写模式、自动创建和多线程支持。
- DatabasePath:提供数据库文件的完整路径,将应用程序数据目录与数据库文件名结合起来。
三、延迟初始化
SQLiteAsyncConnection Database;public class TodoItemDatabase
{SQLiteAsyncConnection Database;//用于异步操作SQLite数据库的连接对象。public TodoItemDatabase()//这是 TodoItemDatabase 类的默认构造函数。当前它是空的,并没有执行任何操作。这意味着在创建 TodoItemDatabase 类的实例时,不会立即进行任何初始化工作。{}async Task Init()//Init 的异步方法。方法返回类型是 Task,表示这是一个异步操作。{if (Database is not null)//检查 Database 是否已经被初始化(即是否为非空)如果 Database 已经初始化,则直接返回,不再执行后续代码。这可以防止重复初始化。return;Database = new SQLiteAsyncConnection(Constants.DatabasePath, Constants.Flags);//创建一个新的 SQLiteAsyncConnection 实例。var result = await Database.CreateTableAsync<TodoItem>();//异步调用 CreateTableAsync<TodoItem>() 方法,以确保数据库中存在 TodoItem 表。如果表不存在,这个方法会创建它。由于使用了 await 关键字,代码将在这一行异步等待操作完成,然后继续执行。}...
}
总结
以下是 TodoItemDatabase 类及其 Init 方法的详细解释:
-
成员变量
SQLiteAsyncConnection Database:用于管理与SQLite数据库的异步连接。
-
构造函数
public TodoItemDatabase():默认构造函数,目前没有进行任何初始化操作。
-
Init方法async Task Init():异步初始化方法。- 首先检查
Database是否已经被初始化。如果已初始化,则直接返回,避免重复初始化。 - 如果未初始化,则创建一个新的
SQLiteAsyncConnection实例,使用指定的数据库路径和打开标志。 - 异步调用
CreateTableAsync<TodoItem>(),确保数据库中存在TodoItem表。
- 首先检查
通过这种方式,TodoItemDatabase 类提供了一种懒加载的机制来初始化数据库连接和表结构。这确保了数据库仅在需要时初始化,并且只会初始化一次,避免重复操作。
四、数据操作方法
TodoItemDatabase 类包括四种类型的数据操作方法:创建、读取、编辑和删除。 SQLite.NET 库提供了一个简单的对象关系映射 (ORM),可用于存储和检索对象,而无需编写 SQL 语句。
public async Task<List<TodoItem>> GetItemsAsync(){await Init();//调用 Init() 方法,确保数据库已经初始化。return await Database.Table<TodoItem>().ToListAsync();//使用 Database.Table<TodoItem>().ToListAsync() 获取 TodoItem 表中的所有记录,并以列表形式返回}public async Task<List<TodoItem>> GetItemsNotDoneAsync(){await Init();//调用 Init() 方法,确保数据库已经初始化。return await Database.Table<TodoItem>().Where(t => t.Done).ToListAsync();//使用 Database.Table<TodoItem>().Where(t => t.Done).ToListAsync() 过滤出 Done 字段为 true 的项目并以列表形式返回。// SQL queries are also possible//return await Database.QueryAsync<TodoItem>("SELECT * FROM [TodoItem] WHERE [Done] = 0");}public async Task<TodoItem> GetItemAsync(int id){await Init();return await Database.Table<TodoItem>().Where(i => i.ID == id).FirstOrDefaultAsync();//使用 Database.Table<TodoItem>().Where(i => i.ID == id).FirstOrDefaultAsync() 查找并返回ID匹配的第一条记录。如果没有找到,返回 null。}public async Task<int> SaveItemAsync(TodoItem item){await Init();if (item.ID != 0)//检查项目的 ID 是否为非零。{return await Database.UpdateAsync(item);//如果 ID 非零,调用 Database.UpdateAsync(item) 更新现有记录。}else{return await Database.InsertAsync(item);//如果 ID 为零,调用 Database.InsertAsync(item) 插入新记录}}public async Task<int> DeleteItemAsync(TodoItem item){await Init();return await Database.DeleteAsync(item);//使用 Database.DeleteAsync(item) 删除提供的项目。}
总结
TodoItemDatabase 类提供了一系列异步方法,以便与SQLite数据库进行交互,处理 TodoItem 表中的数据。这些方法涵盖了常见的CRUD操作(创建、读取、更新、删除),并在每次操作前确保数据库连接已初始化。通过异步编程模式,这些操作不会阻塞调用线程,有助于保持应用程序的响应性。
四、完整代码
using SQLite;
using TodoSQLite.Models;namespace TodoSQLite.Data;public class TodoItemDatabase
{SQLiteAsyncConnection Database;//用于异步操作SQLite数据库的连接对象。public TodoItemDatabase()//这是 TodoItemDatabase 类的默认构造函数。当前它是空的,并没有执行任何操作。这意味着在创建 TodoItemDatabase 类的实例时,不会立即进行任何初始化工作。{}async Task Init()//Init 的异步方法。方法返回类型是 Task,表示这是一个异步操作。{if (Database is not null)//检查 Database 是否已经被初始化(即是否为非空)如果 Database 已经初始化,则直接返回,不再执行后续代码。这可以防止重复初始化。return;Database = new SQLiteAsyncConnection(Constants.DatabasePath, Constants.Flags);//创建一个新的 SQLiteAsyncConnection 实例。var result = await Database.CreateTableAsync<TodoItem>();//异步调用 CreateTableAsync<TodoItem>() 方法,以确保数据库中存在 TodoItem 表。如果表不存在,这个方法会创建它。由于使用了 await 关键字,代码将在这一行异步等待操作完成,然后继续执行。}public async Task<List<TodoItem>> GetItemsAsync(){await Init();//调用 Init() 方法,确保数据库已经初始化。return await Database.Table<TodoItem>().ToListAsync();//使用 Database.Table<TodoItem>().ToListAsync() 获取 TodoItem 表中的所有记录,并以列表形式返回}public async Task<List<TodoItem>> GetItemsNotDoneAsync(){await Init();//调用 Init() 方法,确保数据库已经初始化。return await Database.Table<TodoItem>().Where(t => t.Done).ToListAsync();//使用 Database.Table<TodoItem>().Where(t => t.Done).ToListAsync() 过滤出 Done 字段为 true 的项目并以列表形式返回。// SQL queries are also possible//return await Database.QueryAsync<TodoItem>("SELECT * FROM [TodoItem] WHERE [Done] = 0");}public async Task<TodoItem> GetItemAsync(int id){await Init();return await Database.Table<TodoItem>().Where(i => i.ID == id).FirstOrDefaultAsync();//使用 Database.Table<TodoItem>().Where(i => i.ID == id).FirstOrDefaultAsync() 查找并返回ID匹配的第一条记录。如果没有找到,返回 null。}public async Task<int> SaveItemAsync(TodoItem item){await Init();if (item.ID != 0)//检查项目的 ID 是否为非零。{return await Database.UpdateAsync(item);//如果 ID 非零,调用 Database.UpdateAsync(item) 更新现有记录。}else{return await Database.InsertAsync(item);//如果 ID 为零,调用 Database.InsertAsync(item) 插入新记录}}public async Task<int> DeleteItemAsync(TodoItem item){await Init();return await Database.DeleteAsync(item);//使用 Database.DeleteAsync(item) 删除提供的项目。}
}
五、扩展思路创建多个表及相关字段
当需要在SQLite数据库中创建多个表时,可以根据每个表的需求定义相应的数据模型类,并使用SQLiteAsyncConnection来执行创建表的操作。下面是一个示例,演示了如何创建多个表及相关字段:
using SQLite;namespace TodoSQLite.Models
{public class TodoItem{[PrimaryKey, AutoIncrement]public int ID { get; set; }public string Text { get; set; }public bool Done { get; set; }}public class AnotherTableItem{[PrimaryKey, AutoIncrement]public int ID { get; set; }public string Description { get; set; }public DateTime DueDate { get; set; }}
}
在上面的示例中,我们定义了两个数据模型类 TodoItem 和 AnotherTableItem,分别用于表示不同的表。每个类对应一个表,每个属性对应表中的一个字段。在这里,TodoItem 表包含 ID、Text 和 Done 三个字段,而 AnotherTableItem 表包含 ID、Description 和 DueDate 三个字段。
然后,在 TodoItemDatabase 类中,可以添加额外的方法来处理新增的表,包括创建、读取、更新和删除操作。例如:
public class TodoItemDatabase
{// 其他代码...public async Task CreateTableAsync<T>(){await Database.CreateTableAsync<T>();}public async Task<List<AnotherTableItem>> GetAnotherTableItemsAsync(){await Init();return await Database.Table<AnotherTableItem>().ToListAsync();}// 其他表相关的方法...
}
完整代码
using SQLite;
using System.Collections.Generic;
using System.Threading.Tasks;namespace TodoSQLite
{public class TodoItemDatabase{private readonly SQLiteAsyncConnection _database;public TodoItemDatabase(){_database = new SQLiteAsyncConnection(Constants.DatabasePath, Constants.Flags);InitializeTables().Wait();}private async Task InitializeTables(){await _database.CreateTableAsync<TodoItem>();await _database.CreateTableAsync<AnotherTableItem>();}// 获取所有TodoItem项public Task<List<TodoItem>> GetItemsAsync(){return _database.Table<TodoItem>().ToListAsync();}// 获取未完成的TodoItem项public Task<List<TodoItem>> GetItemsNotDoneAsync(){return _database.Table<TodoItem>().Where(t => !t.Done).ToListAsync();}// 根据ID获取单个TodoItem项public Task<TodoItem> GetItemAsync(int id){return _database.Table<TodoItem>().Where(i => i.ID == id).FirstOrDefaultAsync();}// 保存或更新TodoItem项public Task<int> SaveItemAsync(TodoItem item){if (item.ID != 0){return _database.UpdateAsync(item);}else{return _database.InsertAsync(item);}}// 删除TodoItem项public Task<int> DeleteItemAsync(TodoItem item){return _database.DeleteAsync(item);}// 获取所有AnotherTableItem项public Task<List<AnotherTableItem>> GetAnotherTableItemsAsync(){return _database.Table<AnotherTableItem>().ToListAsync();}// 保存或更新AnotherTableItem项public Task<int> SaveAnotherTableItemAsync(AnotherTableItem item){if (item.ID != 0){return _database.UpdateAsync(item);}else{return _database.InsertAsync(item);}}// 删除AnotherTableItem项public Task<int> DeleteAnotherTableItemAsync(AnotherTableItem item){return _database.DeleteAsync(item);}}
}
-
TodoItemDatabase 类:
- 构造函数采用了
Constants.DatabasePath和Constants.Flags来初始化数据库连接。 - 把表的创建操作移动到了一个独立的私有异步方法
InitializeTables中,这样在构造函数中调用时更加清晰。 - 所有其他的方法保持不变,只是稍微调整了一下注释以符合新的代码结构。
- 构造函数采用了
完整思路都有了,仔细阅读,必能成功!
关联阅读
.NET MAUI Sqlite数据库操作(一)
.NET MAUI Sqlite数据库操作(二)异步初始化方法
相关文章:
.NET MAUI Sqlite数据库操作(一)
一、安装 NuGet 包 安装 sqlite-net-pcl 安装 SQLitePCLRawEx.bundle_green 二、配置数据库(数据库文件名和路径) namespace TodoSQLite; public static class Constants {public const string DatabaseFilename "TodoSQLite.db3";//数据库…...
SQL 窗口函数
1.窗口函数之排序函数 RANK, DENSE_RANK, ROW_NUMBER RANK函数 计算排序时,如果存在相同位次的记录,则会跳过之后的位次 有 3 条记录排在第 1 位时: 1 位、1 位、1 位、4 位…DENSE_RANK函数 同样是计算排序,即使存在相同位次的记录,也不会跳过之后的位次 有 3 条记录排在…...
staruml怎么合并多个Project工程文件
如图现在有两个staruml文件 现在我想要把project2合并到project1里面 步骤如下: 1、首先打开project2 2、如图选择导出Fragment 3、选中自己想导出的模块(可以不止一个) 4、将其保存在桌面 5、打开project1 6、选择导入 7、选中刚刚…...
设计模式——外观模式
外观模式(Facade) 为系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。 #include <iostream>using namespace std;// 四个系统子类 class SubSystemOne { public:void MethodOne(){cout <&l…...
开源-Docker部署Cook菜谱工具
开源-Docker部署Cook菜谱工具 文章目录 开源-Docker部署Cook菜谱工具介绍资源列表基础环境一、安装Docker二、配置加速器三、查看Docker版本四、拉取cook镜像五、部署cook菜谱工具5.1、创建cook容器5.2、查看容器运行状态5.3、查看cook容器日志 六、访问cook菜谱服务6.1、访问c…...
使用PHP对接企业微信审批接口的问题与解决办法(二)
在现代企业中,审批流程是非常重要的一环,它涉及到企业内部各种业务流程的规范和高效运转。而随着企业微信的流行,许多企业希望将审批流程整合到企业微信中,以实现更便捷的审批操作。本文将介绍如何使用PHP对接企业微信审批接口&am…...
RK3288 android7.1 实现ota升级时清除用户数据
一,OTA简介(整包,差分包) OTA全称为Over-The-Air technology(空中下载技术),通过移动通信的接口实现对软件进行远程管理。 1. 用途: OTA两种类型最大的区别莫过于他们的”出发点“(我们对两种不同升级包的创建&…...
okHttp的https请求忽略ssl证书认证
使用okhttp请求第三方https接口返回异常 sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target意思就是非安全的调用&#…...
在Java中使用Spring Boot设置全局的BusinessException
在线工具站 推荐一个程序员在线工具站:程序员常用工具(http://cxytools.com),有时间戳、JSON格式化、文本对比、HASH生成、UUID生成等常用工具,效率加倍嘎嘎好用。 程序员资料站 推荐一个程序员编程资料站:…...
Java 异常处理 -- Java 语言的异常、异常链与断言
大家好,我是栗筝i,这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 009 篇文章,在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验,并希望进一步完善自己对整个 Java 技术体系来充实自…...
Spring Cloud Nacos 详解:服务注册与发现及配置管理平台
Spring Cloud Nacos 详解:服务注册与发现及配置管理平台 Spring Cloud Nacos 是 Spring Cloud 生态系统中的一个子项目,提供了服务注册与发现、配置管理等功能,基于 Alibaba 开源的 Nacos 项目。Nacos 是一个易于使用的动态服务发现、配置管…...
java多线程临界区介绍
在Java多线程编程中,"临界区"是指一段必须互斥执行的代码区域。当多个线程访问共享资源时,为了防止数据不一致或逻辑错误,需要确保同一时刻只有一个线程可以进入临界区。Java提供了多种机制来实现这一点,例如synchroniz…...
基于JSP的超市管理系统
你好呀,我是计算机学长猫哥!如果有相关需求,文末可以找到我的联系方式。 开发语言:Java 数据库:MySQL 技术:JSP MyBatis 工具:IDEA/Eclipse、Navicat、Maven 系统展示 员工管理界面图 管…...
一文讲清:生产报工系统的功能、报价以及如何选择
最近这几年,企业越来越注重生产的速度和成本,尤其是“性价比”,生产报工系统已经变成了制造业里不可或缺的一部分。不过,市场上生产报工系统的选择太多,价格也都不一样,这就给很多企业出了个难题࿱…...
blender bpy将顶点颜色转换为UV纹理vertex color to texture
一、关于环境 安装blender的bpy,不需要额外再安装blender软件。在python控制台中直接输入pip install bpy即可。 二、关于代码 本文所给出代码仅为参考,禁止转载和引用,仅供个人学习。 本文所给出的例子是https://download.csdn.net/downl…...
Flink Sql:四种Join方式详解(基于flink1.15官方文档)
JOINs flink sql主要有四种连接方式,分别是Regular Joins、Interval Joins、Temporal Joins、lookup join 1、Regular Joins(常规连接 ) 这种连接方式和hive sql中的join是一样的,包括inner join,left joinÿ…...
(delphi11最新学习资料) Object Pascal 学习笔记---第14章泛型第3节(泛型约束)
14.3 泛型约束 正如我们所看到的,您在泛型类的方法中可以做的事情非常少。您可以传递它(即分配它)并执行上面我介绍的泛型类型函数允许的有限操作。 为了能够执行泛型类的实际操作,通常需要对其进行约束。例如,…...
C语言详解(预编译)
Hi~!这里是奋斗的小羊,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~ 💥💥个人主页:奋斗的小羊 💥💥所属专栏:C语言 🚀本系列文章为个人学习…...
解决el-table表格拖拽后,只改变了数据,表头没变的问题
先看看是不是你想要解决的问题 拖拽后表头不变的bug修复 这个问题一般是使用v-for对column的数据进行循环的时候,key值绑定的是个index导致的,请看我上篇文章:eleplus对el-table表格进行拖拽(使用sortablejs进行列拖拽和行拖拽):-…...
简单塔防小游戏
学习目标:熟悉塔防游戏核心战斗 游戏画面 项目结构目录 核心代码: if ( Input.GetMouseButtonDown(0)){if (EventSystem.current.IsPointerOverGameObject()false){//开发炮台的建造Ray ray Camera.main.ScreenPointToRay(Input.mousePosition);Rayca…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
