.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 方法的详细解释:

  1. 成员变量

    • SQLiteAsyncConnection Database:用于管理与SQLite数据库的异步连接。
  2. 构造函数

    • public TodoItemDatabase():默认构造函数,目前没有进行任何初始化操作。
  3. 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; }}
}

在上面的示例中,我们定义了两个数据模型类 TodoItemAnotherTableItem,分别用于表示不同的表。每个类对应一个表,每个属性对应表中的一个字段。在这里,TodoItem 表包含 IDTextDone 三个字段,而 AnotherTableItem 表包含 IDDescriptionDueDate 三个字段。

然后,在 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);}}
}

  1. TodoItemDatabase 类:

    • 构造函数采用了 Constants.DatabasePath 和 Constants.Flags 来初始化数据库连接。
    • 把表的创建操作移动到了一个独立的私有异步方法 InitializeTables 中,这样在构造函数中调用时更加清晰。
    • 所有其他的方法保持不变,只是稍微调整了一下注释以符合新的代码结构。

完整思路都有了,仔细阅读,必能成功!

关联阅读
.NET MAUI Sqlite数据库操作(一)

.NET MAUI Sqlite数据库操作(二)异步初始化方法 

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

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

相关文章

this指针如何使C++成员指针可调用

在C中&#xff0c;this指针是一个隐藏的指针&#xff0c;指向当前对象实例。它在成员函数中自动可用&#xff0c;用于访问该对象的成员变量和成员函数。理解this指针的工作原理有助于理解为什么指向成员的指针是可调用的。在本文中&#xff0c;我们将详细探讨this指针的概念&am…

云计算在保险行业的应用:太平财险团财险理赔新核心业务系统案例

随着科技的快速发展&#xff0c;云计算技术已经成为推动保险行业数字化转型的重要力量。云计算为保险公司提供了弹性、可扩展的计算资源&#xff0c;使其能够灵活应对业务高峰和低谷&#xff0c;提高业务运营效率和风控水平。太平财险与太平金科联合开发的“团财险理赔新核心业…

PCA与LDA

共同点 降维方法&#xff1a; PCA和LDA都是数据降维的方式&#xff0c;它们都能通过某种变换将原始高维数据投影到低维空间。 数学原理&#xff1a; 两者在降维过程中都使用了矩阵特征分解的思想&#xff0c;通过对数据的协方差矩阵或类间、类内散度矩阵进行特征分解&#xff…

JAVA开发 选择指定的文件生成ZIP压缩包

JAVA开发 选择指定的文件生成ZIP压缩包 1、ZipOutputStream1.1 主要方法1.2 使用步骤 2、案例实现2.1 代码块2.2 运行界面 1、ZipOutputStream ZipOutputStream 是 Java 中的一个类&#xff0c;它属于 java.util.zip 包&#xff0c;用于将多个文件或数据流写入到一个 ZIP 输出…

【mysql为什么采用b+树作为索引】

## 1、Hash: 它查询任何一行数据都只需一次IO,但是只能查一行&#xff0c;不能查询范围 。 ## 2、二叉树&#xff1a; 1、 可能会单边增长&#xff0c;退化成链表&#xff0c;查询效率和没建立索引差不多。2、才二叉而已&#xff0c;树的层数太多&#xff0c;IO次数多&#x…

贪心算法学习五

例题一 解法&#xff08;贪⼼&#xff09;&#xff1a; 贪⼼策略&#xff1a; 我们的任何选择&#xff0c;应该让这个数尽可能快的变成 1 。 对于偶数&#xff1a;只能执⾏除 2 操作&#xff0c;没有什么分析的&#xff1b; 对于奇数&#xff1a; i. 当 n 1 的时候…

Docker 安装 MySQL5.7 和 MySQL8

文章目录 安装 MySQL5.7拉取镜像前期准备启动容器 安装MySQL8.0拉取镜像查看镜像前期准备启动容器 安装 MySQL5.7 拉取镜像 docker pull mysql:5.7拉下来镜像后 执行 docker images 此时我们已经有这个镜像了。 前期准备 在根目录下创建 app &#xff0c; 在 app 目录下创建…

小工具开发

因不太喜欢重复性工作&#xff0c;为了提高日常工作效率&#xff0c;在业余时间开发一些小工具用于帮助自己“偷懒”。 小工具功能&#xff1a; 1、Hightec编译的hex文件&#xff0c;与多模式标定hex文件合成 2、Bootloader文件&#xff0c;Hightec编译的hex文件&#xff0c;与…

Oracle 系列数据库使用 listagg去重,删除重复数据的几种方法

listagg聚合之后很多重复数据&#xff0c;下面是解决重复数据问题 案例表 create table "dept_tag_info" ( "tag_id" bigint not null, "tag_code" varchar(200), "tag_name" varchar(500), "tag_level" varchar(200), &…

Android Studio新增功能:Device Streaming

今天将Android Studio升级到2023.3.1 Patch2。发现新增了Device Streaming功能。支持远程使用Google的物理设备调试程序。这样可以方便地在真实设备上测试自己的APP。这对于手头没有Google设备的开发者而言&#xff0c;确实方便很多。该功能目前处于测试阶段&#xff0c;在2025…

交易中的群体行为特征和决策模型

本文基于人的行为和心理特征&#xff0c;归纳出交易中群体的行为决策模型&#xff0c;并基于这个模型&#xff0c;分析股价波浪运行背后的逻辑&#xff0c;以及投机情绪的周期变化规律&#xff0c;以此指导交易&#xff0c;分析潜在的风险和机会&#xff0c;寻找并等待高性价比…

system与excel族函数区别

1.system #include<stdlib.h> int system(const char *command); comand是命令的路径&#xff0c;一般我们用绝对路径 system函数会创建新的进程&#xff0c;新的进程执行完返回原来的进程&#xff0c;原来的进程则继续执行后面的代码段。 如我们创建一个sys.cpp文件…

使用pip2pi和nginx搭建私有pip镜像源方法

在内网环境下部署python开发环境&#xff0c;安装python第三方库比较麻烦&#xff0c;特别是安装需要多个依赖的库。一种比较好的解决方案是搭建一个本地的私有pip镜像源&#xff0c;有多个方案可以选择&#xff0c;比如pypiserver、pip2pi等&#xff0c;本文介绍使用python的p…

Python求子数组和的所有元素(附Demo)

目录 前言1. 暴力求解2. 前缀和哈希表3. 滑动窗口 前言 工作需要&#xff0c;对应需要优化查找子数组和等于特定值的算法 对应的算法推荐&#xff1a;子数组相关题目 以下算法主要针对Python 1. 暴力求解 双重循环时间复杂度为 O(n2) def subarrays_with_sum_equal_k(num…

HTML的常用标签

HTML&#xff08;补&#xff09; CSS选择器 元素选择器&#xff1a;指定一个标签给这个标签设置一个默认的样式。设置的样式对所有相同的标签都有用。 id选择器&#xff1a;我们可以给标签指定一个唯一的id&#xff0c;然后根据id可以在style标签中设置对应标签的样式元素。设…

【仿真建模-anylogic】FlowchartBlock原理解析

Author&#xff1a;赵志乾 Date&#xff1a;2024-06-17 Declaration&#xff1a;All Right Reserved&#xff01;&#xff01;&#xff01; 1. 类图 2. 原理解析 2.1 核心函数 函数功能FlowchartBlock(Engine engine ,Agent owner, AgentList population )构造函数&#xff…

Day 24:100301. 构成整天的下标对数目II

Leetcode 100301. 构成整天的下标对数目II 给你一个整数数组 hours&#xff0c;表示以 **小时 **为单位的时间&#xff0c;返回一个整数&#xff0c;表示满足 i < j 且 hours[i] hours[j] 构成 **整天 **的下标对 i, j 的数目。 **整天 **定义为时间持续时间是 24 小时的 *…

助力樱桃智能自动化采摘,基于YOLOv5全系列【n/s/m/l/x】参数模型开发构建果园种植采摘场景下樱桃成熟度智能检测识别系统

随着科技的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;技术已经渗透到我们生活的方方面面&#xff0c;从智能家居到自动驾驶&#xff0c;再到医疗健康&#xff0c;其影响力无处不在。然而&#xff0c;当我们把目光转向中国的农业领域时&#xff0c;一个令人惊讶的…

虾皮平台API:获取商品买家评论数据

一、接口核心功能 在电商领域&#xff0c;买家评论对于商品的销售和商家的口碑至关重要。虾皮作为东南亚地区知名的电商平台&#xff0c;为商家提供了丰富的商品买家评论数据。为了方便商家获取这些数据&#xff0c;我们的API接口服务其核心功能就是获取商品买家评论数据信息。…

docker和docker compose 部署

一. 将微服务运行在docker上&#xff1a; 1.新建一个空文件夹docker-demo&#xff0c;在里面再新建文件夹app&#xff0c;在app目录下新建一个名为Dockerfile的文件。 2.编写Dockerfile文件 3.构建镜像 4.启动镜像 5.可以访问了。 二使用Dockerfile构建微服务镜像 1.将j…