.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…...
高考之后第一张大流量卡应该怎么选?
高考之后第一张大流量卡应该怎么选? 高考结束后,选择一张合适的大流量卡对于准大学生来说非常重要,因为假期期间流量的使用可能会暴增。需要综合考虑多个因素,以确保选到最适合自己需求、性价比较高且稳定的套餐。以下是一些建议…...
如何从微软官方下载Edge浏览器的完整离线安装包
文章目录 📖 介绍 📖🏡 演示环境 🏡📒 正文内容 📒🚀 官方直链下载🚬 手动选择下载🎈 获取方式 🎈⚓️ 相关链接 ⚓️📖 介绍 📖 在网上搜索Microsoft Edge浏览器的离线安装包时,很多用户都会发现大部分都是在线安装包,无法满足他们在无网络环境下进…...
git 常用的命令
git 常用的命令 一、基础命令1.1 初始化1.2 添加文件1.3 查看缓存区中的文件1.4 查看上次提交到缓存区中的文件1.5 文件从缓存区取出1.6 提交文件1.6 查看提交中包含的文件1.7 查看commit记录 二、回退命令2.1 git reset2.2 将文件从暂存区取出2.3 将文件从仓库取出2.3.1 保留工…...
【StableDiffusion】Embedding 底层原理,Prompt Embedding,嵌入向量
Embedding 是什么? Embedding 是将自然语言词汇,映射为 固定长度 的词向量 的技术 说到这里,需要介绍一下 One-Hot 编码 是什么。 One-Hot 编码 使用了众多 5000 长度的1维矩阵,每个矩阵代表一个词语。 这有坏处,…...
计算机网络(2) 网络层:IP服务模型
一.Internet Protocol在TCP/IP四层模型中的作用 第三层网络层负责数据包从哪里来到哪里去的问题。传输层的数据段提交给网络层后,网络层负责添加IP段,包含数据包源地址与目的地址。将添加IP段的数据包交由数据链路层添加链路头形成最终在各节点传输中所需…...
新人学习笔记之(初识C语言)
一、C语言的简介 1.C语言:1978年1月1日美国贝尔实验室推出的一门非常哇塞计算机语言 2.计算机语言:人与计算机之间进行信息交流沟通的一种特殊语言 二、C语言能做什么 1.操作系统 2.驱动开发 3.引擎开发 4.游戏开发 5.嵌入式开发 三、学习C语言的好处 …...
Unity EasyRoads3D插件使用
一、插件介绍 描述 Unity 中的道路基础设施和参数化建模 在 Unity 中使用内置的可自定义动态交叉预制件和基于您自己导入的模型的自定义交叉预制件,直接创建独特的道路网络。 添加额外辅助对象,让你的场景栩栩如生:桥梁、安全护栏、栅栏、墙壁…...
Redis 地理散列GeoHash
用数据库来算附近的人 地图元素的位置数据使用二维的经纬度表示,经度范围(-180,180],纬度范围 (-90,90],纬度正负以赤道为界,北正南负,经度正负已本初子午线(英国格林尼…...
vim 显示行号
在 Vim 中,你可以通过几种不同的方式来显示行号。以下是两种常用的方法: 临时显示行号: 当你打开 Vim 并想要临时查看文件的行号时,你可以使用 :set number 命令。这个命令会在当前 Vim 会话中显示行号。如果你想要关闭行号显示&a…...
C++:调整数组顺序使奇数位于偶数前面【面试】
在C,如果要调整数组顺序使所有奇数位于偶数前面,这里提供一种简单且常用的方法:双指针技术。这种方法不需要额外的空间,并且时间复杂度为O(n)。 以下是使用双指针技术实现的示例代码: #include <iostream> #in…...
php中switch做网站/seo提供服务
配置 ROS 的 apt 源 ROS的apt源有官方源、国内 USTC 源或新加坡源可供选择, 选择其一就可以了,建议使用国内 USTC 源或新加坡源,安装速度会快很多。 方式一:官方源$ sudo sh -c echo "deb http://packages.ros.org/ros/ubunt…...
做网站 请示/模板自助建站
空间中三维坐标变换一般由三种方式实现,第一种是旋转矩阵和旋转向量;第二种是欧拉角;第三种是四元数。这里先介绍旋转矩阵(旋转向量)与欧拉角实现三维空间坐标变换的方法以及两者之间的关系。 这里以常见的世界坐标系与相机坐标系间的变换为例…...
做佛教网站/软文文案
本文内容学习自:https://morvanzhou.github.io/tutorials/data-manipulation/np-pd/2-2-np-array/ 用 arange 创建连续数组: a np.arange(10,20,2) # 10-19 的数据,2步长 """ array([10, 12, 14, 16, 18]) """ 使用 re…...
网页开发简历模板/seo项目完整流程
本文分为两部分:一、介绍redis分布式锁的原理和使用方法;二、使用redis分布式锁实现一个简单的秒杀系统。 注意:本文使用java语言,最后的例子为springboot项目。但是原理是一样的。 目录 redis分布式锁 原理 进阶 锁过期时间…...
村庄建设网站/体验营销理论
一、首先检查网页中的加载路径是否正确,如果和文件所在路径不一致,就把html改下路径 二、加载路径和文件实际路径一致,看下配置文件: STATIC_URL /static/STATIC_ROOT os.path.join(BASE_DIR, static) 如果还是无法加载…...
做网站需要投标吗/google谷歌
工业机器人现场调试需注意的事项 机器人的安装是在在现场进行的,而真正的生产作业环境会受空间利用率等方面影响,致使机器人的很多姿态受到一定的限制,而这就很容易导致工业机器人在实际工作中,出现震动、移位等现象,…...