.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数据库操作(二)异步初始化方法 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MonoNodes – LOOK / LAB / PRINT DCTLS 复古美学柯达富士胶片负片模拟电影感DCTL达芬奇插件

MonoNodes – LOOK / LAB / PRINT DCTLS&#xff0c;我们包装中的“MONOLOOK”DCTL 的灵感来自柯达和富士的经典胶片美学。这些工具提供了三种特定的负片仿真&#xff0c;每种都经过精心设计&#xff0c;以捕捉模拟胶片的独特色彩质量。它们专为希望将胶片的永恒魅力与数字传感…

文心智能体体验,打造你自己的GPTs应用

利用百度智能体搭建的《RPG冒险游戏大作战》已经发布啦&#xff01; RPG冒险游戏大作战 玩家扮演一位小小勇士女孩&#xff0c;从被巨龙毁灭的冒险小镇出发&#xff0c;一路披荆斩棘&#xff0c;集齐四件神器后&#xff0c;打败巨龙&#xff0c;夺回小镇的安宁&#xff01; 整…

ESP32s3与Lsm6ds3通信---i2c【开源】

接线 ESPS3&#xff0c;I2C的初始化 #ifdef __cplusplus extern "C" { #endif #define I2C_MASTER_SCL_IO CONFIG_I2C_MASTER_SCL /*!< GPIO number used for I2C master clock */ #define I2C_MASTER_SDA_IO CONFIG_I2C_MASTER_SDA …

深度学习笔记: 最详尽Airbnb租赁搜索排名设计

欢迎收藏Star我的Machine Learning Blog:https://github.com/purepisces/Wenqing-Machine_Learning_Blog。如果收藏star, 有问题可以随时与我交流, 谢谢大家&#xff01; Airbnb租赁搜索排名 1. 问题陈述 Airbnb用户在特定地点搜索可用房源。系统应在搜索结果中对多个房源进…

短剧APP开发,线上观看短剧成为“主流”

短剧作为一种新型的影视模式&#xff0c;热度持续飙升&#xff0c;受到了大众的欢迎&#xff0c;成为影视行业一个新的风口赛道。短剧时长短、节奏快、剧情爽&#xff0c;在当下快节奏生活中&#xff0c;能够给大众带来娱乐消遣新方式。 短剧题材丰富多样&#xff0c;从总裁、…

vlc多媒体播放器(支持各种本地视频、网络视频、音频及摄像头直播地址)winform(支持全屏)自动适应x86、x64平台插件及重要代码

1、学习vlcControl1及libvlc.dll类方法(x86为例)最新v3.0.21 1.1 本博文以控件(vlcControl1)方式为主介绍 1.2 安装-引用,添加控件到窗体 using Vlc.DotNet.Forms; 1.3 窗体布局、编写代码 打开文件(以本地媒体文件为主)打开地址(以网络媒体地址为主)播放|暂停功能停…

【数据结构】双向链表(C语言)

哈喽铁子们&#xff0c;这里是博主鳄鱼皮坡。这篇文章将分享交流双向链表的相关知识&#xff0c;下面正式开始。 1. 双向链表的结构 注意&#xff1a;这里的“带头”跟前面我们说的“头节点”是两个概念&#xff0c;实际前面的在单链表阶段称呼不严 谨&#xff0c;但是为了老…

如何利用智能家居打造一个“会呼吸的家”?一体化电动窗帘

如何利用智能家居打造一个“会呼吸的家”&#xff1f;一体化电动窗帘 史新华 隐藏式一体化智能电动窗帘与市面上其他窗帘不同的是&#xff0c;电机内置于轨道之中&#xff0c;一体化&#xff0c;美观、安静、滑动顺畅。 每次都会自动打开和关闭&#xff0c;相当漂亮。 众多家庭…

AI驱动的“黑匣子”可能使手术更安全

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

树莓派4B_OpenCv学习笔记6:OpenCv识别已知颜色_运用掩膜

今日继续学习树莓派4B 4G&#xff1a;&#xff08;Raspberry Pi&#xff0c;简称RPi或RasPi&#xff09; 本人所用树莓派4B 装载的系统与版本如下: 版本可用命令 (lsb_release -a) 查询: Opencv 版本是4.5.1&#xff1a; 学了这些OpenCv的理论性知识&#xff0c;不进行实践实在…

0603 BJT射极耦合差分式放大电路

6.2.3 BJT射极耦合差分式放大电路 电路组成 静态分析 动态分析 仅差模信号输入时 双端输出时电压增益 单端输出时电压增益 单端输入时 差模输入电阻 输出电阻 仅共模信号输入时 带有源负载的射极耦合差分式放大电路

Hvv--知攻善防应急响应靶机--Linux1

HW–应急响应靶机–Linux1 所有靶机均来自 知攻善防实验室 靶机整理&#xff1a; 夸克网盘&#xff1a;https://pan.quark.cn/s/4b6dffd0c51a#/list/share百度云盘&#xff1a;https://pan.baidu.com/s/1NnrS5asrS1Pw6LUbexewuA?pwdtxmy 官方WP&#xff1a;https://mp.weixin.…

【每日一题】二进制中1的个数

二进制中1的个数 ✨ 思路&#xff1a;要求的是一个整形的数&#xff0c;其二进制的位数中有几个1 ✨二进制位就想到了按位操作符&#xff0c;和位移操作符都是对二进制位进行操作的 &1 可以检查最低位是0还是1 移位>>就可以控制最低位的位置&#xff0c;我们让最…

# 钢材刀具的硬度、强度、韧性、耐磨性概念理解

钢材刀具的硬度、强度、韧性、耐磨性概念理解 文章目录 钢材刀具的硬度、强度、韧性、耐磨性概念理解A 简洁表述B 详细描述1 硬度2 强度3 韧性4 耐磨性 C 懂了吧 钢材刀具的硬度、强度、韧性、耐磨性经常把人搞疯&#xff0c;概念表达纠缠在一起&#xff0c;难以完全理解&#…

流媒体学习之路(WebRTC)——音频NackTracker优化思路(8)

流媒体学习之路(WebRTC)——音频NackTracker优化思路&#xff08;8&#xff09; —— 我正在的github给大家开发一个用于做实验的项目 —— github.com/qw225967/Bifrost目标&#xff1a;可以让大家熟悉各类Qos能力、带宽估计能力&#xff0c;提供每个环节关键参数调节接口并实…

LeetCode | 58.最后一个单词的长度

这道题要求最后一个单词的长度&#xff0c;第一个想到的就是反向遍历字符串&#xff0c;寻找最后一个单词并计算其长度。由于尾部可能会有’ &#xff0c;所以我们从后往前遍历字符串&#xff0c;找到第一个非空格的字符&#xff0c;然后记录下到下一个空格前依次有多少个字母即…

HCIA1 华为VRP系统基本操作

1.实验组网介绍 使用PC电脑通过串口线&#xff0c;直连1台全新的路由器console port&#xff0c;进行简单配置。 2.配置思路 2.1配置设备名称 2.2配置路由器接口地址 2.3保存配置并重启设备 3.配置步骤 3.1 Console方式登录 略 3.2查看设备版本信息 3.3设备基本配置 &am…

【全开源】快递寄件小程序源码(FastAdmin+ThinkPHP+原生微信小程序)

&#x1f4e6;快递寄件小程序&#xff1a;轻松寄送&#xff0c;便捷生活 &#x1f69a;一、引言&#xff1a;告别繁琐&#xff0c;让寄件更简单 在繁忙的生活中&#xff0c;寄送快递往往成为我们的一大难题。传统的寄件方式需要前往快递公司网点&#xff0c;填写繁琐的寄件信…

css系列:音频播放效果-波纹律动

介绍 语音播放的律动效果&#xff0c;通俗来说就是一个带动画的特殊样式的进度条&#xff0c;播放的部分带有上下律动的动画&#xff0c;未播放的部分是普通的灰色竖状条。 实现中夹带了less变量、继承和循环遍历&#xff0c;可以顺带学习一下。 结果展示 大致效果如图所示…

山东大学软件学院项目实训-创新实训-基于大模型的旅游平台(三十二)- 微服务(12)

目录 12.8 RestClient查询文档 12.8.1 快速入门 12.8.2 match&#xff0c; term&#xff0c;bool&#xff0c;range查询 12.8.3 排序和分页 12.8.4 高亮 12.8 RestClient查询文档 12.8.1 快速入门 Testvoid testMatchALL() throws IOException {// 1. 准备requestSearchReq…