百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

使用 SQLite 在本地存储数据 如何使用SQLite保存数据

liebian365 2024-11-13 13:25 7 浏览 0 评论

拥有关系数据时,在 SQLite 中存储数据十分有用。 例如,假设正在生成用于管理图书馆的应用程序。 图书馆中的每本书都有一位或多位作者,而一名作者可以写多本书。 可在 SQLite 数据库中轻松地为这种关系建模。

本单元将介绍如何通过 SQLite.NET 在 Xamarin 应用程序中使用 SQLite。

什么是 SQLite?

SQLite 是轻型跨平台本地数据库,其已成为移动应用程序的行业标准。 SQLite 不在服务器上运行,并存储在设备文件系统上的单一磁盘文件中。 所有读写操作都直接针对 SQLite 磁盘文件运行。

SQLite 本机库默认内置于 Android 和 iOS 中;但其引擎只支持 C/C++ API。 对于想要 SQLite 和 .NET 通过某种方式进行交互的 .NET 开发人员来说,此方案并不理想。

备注:如果想要下载 SQLite.NET,可在此处找到它:https://www.nuget.org/packages/sqlite-net


什么是 SQLite.NET?

C++学习资料→CC++入门到高级资料

本机 SQLite 引擎有多个 C# 包装器可供 .NET 开发人员使用。 许多 Xamarin 开发人员使用名为 SQLite.NET 的常用 C# 包装器。

SQLite.NET 是对象关系映射器。 它通过让我们能够将在项目中定义的模型用作架构,帮助简化定义数据库架构的过程。 以下面的代码片段为例:

class User
{
    public int Id { get; set; }
    public string Username { get; set; }
    ...
}

借助对象关系映射器,可使用此初始“User” 类,并让其自动创建包含“Id”和“Username”列的名为“User”的数据库表。

SQLite.NET 作为 NuGet 包提供。 将它添加到 Xamarin.Forms 的每个项目中。

如何连接到 SQLite 数据库

SQLite.Net 通过“SQLiteConnection”对象建立与 SQLite 数据库的连接。 实例化此对象时,必须传入数据库文件的文件名。 然后,它将打开文件(如果存在文件)或创建文件(如果不存在文件)。

下面是其用法示例:

string filename = ...
SQLiteConnection conn = new SQLiteConnection(filename);

请注意,filename 需要指向应用沙盒中的位置。

如何创建表

回想一下,SQLite.NET 是对象关系映射器,这意味着可以通过 C# 类生成数据库架构。 返回 User 类的上一个示例。

class User
{
    public int Id { get; set; }
    public string Username { get; set; }
    ...
}

SQLite.NET 可通过此 C# 类生成数据库架构,但许多属性可供添加到类中,用于对架构进行修改。

以下是可用属性的一些示例:

  • Table:如果希望表名不是类名,请指定表的名称。
  • primaryKey:指定要为主键的列。
  • AutoIncrement:指定在插入新行时,列值应自动增加。
  • Column:如果不想使用属性名作为列名,请指定列的名称。
  • MaxLength:指定列中可使用的最大字符数。
  • Unique:指定列中的值必须与其他所有行不同。

回到“User”类,下面是使用所有这些属性的更新版本:

[Table("user")]
public class User
{
    // PrimaryKey is typically numeric 
    [PrimaryKey, AutoIncrement, Column("_id")]
    public int Id { get; set; }

    [MaxLength(250), Unique]
    public string Username { get; set; }
    ...
}

定义要用作数据库架构的 C# 类后,需要让 SQLite.NET 创建表。 为此,请在“SQLiteConnection”类上使用“CreateTable”方法。 下面是一个示例:

SQLiteConnection conn = new SQLiteConnection(filename);
conn.CreateTable<User>();

如果调用“CreateTable”方法且表已存在于数据库中,则它将检查架构类,查看是否有任何更改。 如果有任何更改,将执行更新操作,尝试更新数据库架构。

如何执行基本读写操作

创建表后,即可开始与它进行交互。 首先可插入一些数据。 为此,请在 SQLiteConnection 实例上使用 Insert 方法。 例如,如果想要将新的“User”插入数据库,则代码将类似于以下示例:

public int AddNewUser(User user)
{
    int result = conn.Insert(user);
    return result;
}

“Insert”方法返回“int”,其表示插入表中的行数。 在本例中,该数字为 1。

插入数据后,通常需要从表中检索数据。 借助 SQLite.NET,可使用“Table”方法轻松地在表中检索所有行。 以下是如何使用它的示例:

public List<User> GetAllUsers()
{
    List<User> users = conn.Table<User>().ToList();
    return users;
}

“Table”方法返回“TableQueryT”。 若要获取“List”,请使用“ToList”方法。

使用 LINQ 执行 SQLite 查询

虽然可使用“Table”方法在表中检索所有行,但并不总是想要这样做。 有时,想要仅返回行的子集或运行更复杂的查询。 对于这些任务,请将 LINQ 与 SQLite.NET 配合使用。

SQLite.NET 支持许多常见的 LINQ 查询,其中包括:

  • Where
  • Take
  • Skip
  • OrderBy
  • OrderByDescending
  • ThenBy
  • ElementAt
  • First
  • FirstOrDefault
  • ThenByDescending
  • Count

通过这些方法,你可以使用扩展方法语法或 LINQ C# 语法。 例如,下面是可供使用 LINQ C# 语法按用户名获取用户的代码片段:

public User GetByUsername(string username)
{
    var user = from u in conn.Table<Person>()
               where u.Username == username
               select u;
    return user.FirstOrDefault();
}

定义 SQLite.NET 实体

首先,创建用于定义数据库架构的模型类。

  1. 将名为“Models”的新文件夹添加到“People”.NET 标准库中。
  2. 在“Models”文件夹中,创建名为“Person”的新类。 确保将其标记为“公开”。
namespace People.Models
{
   public class Person
   {
   }
}

3.添加名为“ID”的 int 属性。

4.添加名为 Name 的字符串属性。

namespace People.Models
{
   public class Person
   {
      public int Id { get; set; }
      public string Name { get; set; }
   }
}

添加 SQLite.NET 属性

现在已创建了模型,接下来可添加一些属性用于帮助 SQLite.NET 将类映射到表中。

  1. 为 SQLite 命名空间添加 using 指令。 借助该指令,可使用 SQLite.NET 属性。
  2. 使用 [Table] 属性批注“Person”类,并将名称指定为“people”。
  3. 将“Id”属性指定为主键。 使用 [PrimaryKey] 和 [AutoIncrement] 属性对其进行批注。
  4. 向“Name”属性添加注释,以向数据添加一些约束。 将其 [MaxLength] 指定为 250。 指定列中的每个值都应为 [Unique]。
using SQLite;

namespace People.Models
{
   [Table("people")]
   public class Person
   {
      [PrimaryKey, AutoIncrement]
      public int Id { get; set; }

      [MaxLength(250), Unique]
      public string Name { get; set; }
   }
}

5.生成应用程序,确保其能正常编译。


添加存储库类

接下来,需要为跨平台项目添加一些预生成的代码。 已提供此代码。 您可以在练习存储库的克隆或下载副本的文件夹中找到它。

  1. 转到“exercise1”“start”文件夹。
  2. 打开“People.sln”解决方案。
  3. 将“assets”文件夹中的“PersonRepository.cs”C# 源文件添加到“People”共享项目中。 可将其从文件夹拖放到解决方案资源管理器中的项目根节点。
  4. 检查存储库类。 它具有一些预先提供的方法和少量 TODO 标记,将在其中添加一些功能用于访问数据库。

连接到数据库

现在,将在“SQLiteConnection”上创建一个实例,然后创建一个“Person”表。

  1. 打开“PersonRepository.cs”源文件。
  2. 在构造函数中,初始化新的“SQLiteConnection”。 将其分配给名为“conn”的字段。
  3. 使用“conn.CreateTable”方法创建一个表,用于存储“Person”数据。
private SQLiteConnection conn;
...
public PersonRepository(string dbPath)
{
   conn = new SQLiteConnection(dbPath);
   conn.CreateTable<Person>();
}

向数据库中插入行

创建“Person”表后,即可开始插入数据。 实现“AddNewPerson”方法,使用户能够插入新人员。

  1. 在“PersonRepository.cs”中,找到“AddNewPerson”方法。
  2. 添加代码以插入新的“Person”对象。 在“SQLiteConnection”对象上使用“Insert”方法。 将返回值分配给已在方法中定义的“result”变量。
public void AddNewPerson(string name)
{
   int result = 0;
   try
   {
      //basic validation to ensure a name was entered
      if (string.IsNullOrEmpty(name))
            throw new Exception("Valid name required");

      result = conn.Insert(new Person { Name = name });
      ...
   }
   ...
}

从数据库中读取

此时,可以向“Person”表添加新行。 尝试使用“Table”方法读取它们。

  1. 在“PersonRepository.cs”中,找到“GetAllPeople”方法。
  2. 使用 Table<T> 方法检索所有记录。
  3. 无法直接返回枚举器,因为预期为 List<Person>。 使用“ToList()”扩展方法将其转换为有效类型。
  4. 可根据需要,通过将代码包装到 try-catch 块中来包含错误处理流程。 如果存在错误,请将“StatusMessage”属性设置为异常的“消息”并返回空的 。
public List<Person> GetAllPeople()
{
   try
   {
      return conn.Table<Person>().ToList();
   }
   catch (Exception ex)
   {
      StatusMessage = string.Format("Failed to retrieve data. {0}", ex.Message);
   }

   return new List<Person>();
}

连接到 UI

最后一步是添加 UI,以调用在上一步中实现的方法。 使用练习所用的“Assets”文件夹中包含的预生成的 UI。

  1. 将“People”共享项目中的“MainPage.xaml”和“MainPage.xaml.cs”替换为资产中的副本。 将它们直接复制到文件夹结构中并替换现有文件。
  2. 打开 .NET Standard 项目中的“App.xaml.cs”文件,然后找到构造函数。
  3. 将传入的参数重命名为 dbPath(如果它不是该名称)。
  4. 删除“MainPage”对象上的“Text”属性资源库。 你不再拥有该属性,因为刚刚替换了 UI。
  5. 添加名为“PersonRepo”的公共静态属性,用于保存“PersonRepository”对象。
  6. 通过创建“PersonRepository”的实例来初始化构造函数中的“PersonRepo”属性,并将“dbPath”参数传入存储库构造函数。

运行应用程序

生成解决方案,并运行应用程序。 通过在文本框中键入名称并选择“添加人员”,将人员添加到数据库中。

之后,可选择“获取所有人员”,以从数据库中提取名称并将在列表中显示它们。 此外,尝试重启应用程序,查看数据在应用程序启动期间是否还在。


如果以同步方式对数据库运行查询,可能会导致性能问题。 SQLite.NET 具有一个异步 API,可用于使应用程序始终保持响应。

本单元将介绍如何使用 SQLite.NET 的异步 API 来确保应用程序保持高度响应。

了解异步查询

到目前为止,所做的一切均已在 UI 线程上执行。 但是,若要生成响应速度极快的移动应用程序,需要以略有不同的方式执行操作。 如果在 UI 线程上运行数据库操作,则可能会导致 UI 在操作需要很长时间才能完成时冻结。

为了解决此问题,SQLite.NET 通过“SQLiteAsyncConnection”类包含了一个异步 API。 例如,若要异步创建表,可使用

var conn = new SQLiteAsyncConnection(dbPath);
await conn.CreateTableAsync<User>();

SQLite.NET 不是线程安全的。 这意味着如果多个线程使用同一个连接,你可能会遇到问题。 因此,最好有一个负责管理“SQLite”连接的存储库类。

使用 SQLite.NET 执行异步操作

“SQLiteAsyncConnection”公开与同步对应类相同的操作。 但是,操作均基于任务,以便在后台使用。

下面列出了一些常见的异步操作:

  • CreateTableAsync:根据指示的类创建表
  • DropTableAsync:删除与指示的类关联的表
  • GetAsync:获取表中与指示的类关联的记录,并匹配传入构造函数的主键
  • InsertAsync:使用传入构造函数的项插入新记录
  • UpdateAsync:使用传入构造函数的项更新现有记录
  • DeleteAsync:删除表中映射到指示类的记录,并匹配传入构造函数的主键
  • QueryAsync:运行直接 SQL 查询并返回对象
  • ExecuteAsync:运行直接 SQL 查询并返回受影响的行数。
  • ExecuteScalarAsync:运行直接 SQL 查询并返回单个结果
  • ToListAsync:异步执行“Table”方法

以下是使用“ToListAsync”方法异步检索记录的示例:

SQLiteAsyncConnection conn;
ObservableCollection<User> userList;  // Bound to UI
...
public async Task AddAllUsersAsync()
{
    List<User> users = await conn.Table<User>().ToListAsync();
    // Must be on UI thread here!
    foreach (var u in users)
        userList.Add(u);
}

使用“ToListAsync”方法从数据库异步获取所有用户。 如果使用此方法,即使数据库中有大量用户,UI 也能保持响应。

异步使用 SQLite

本单元将把 Person 存储库应用程序从同步 SQLite.NET API 转换为异步版本。 这样一来,无论对数据库执行多少次查询,应用程序将始终能够保持响应。

创建异步连接

首先将“PersonRepository”更改为使用“SQLiteConnection”的异步版本。 现在,可以与数据库进行异步交互。

  1. 打开“People”.NET Standard 项目中的“PersonRepository.cs”文件。
  2. 将“SQLiteConnection”conn 属性更改为“SQLiteAsyncConnection”。 若要进行此更改,必须更新属性和实例化。
  3. 在构造函数中,请注意,对“CreateTable”的调用不再有效。 将此调用替换为“CreateTableAsync”。
private SQLiteAsyncConnection conn;

public PersonRepository(string dbPath)
{
   conn = new SQLiteAsyncConnection(dbPath);
   conn.CreateTableAsync<Person>().Wait();
}

以异步方式向表中插入项

现在使用的是“SQLiteAsyncConnection”,可与数据库进行异步交互。 接下来了解如何以异步方式插入新项。

修改“AddNewPerson”方法,以通过异步插入方式插入新的“Person”。

using System.Threading.Tasks;
...
public async Task AddNewPersonAsync(string name)
{
   int result = 0;
   try
   {
      //basic validation to ensure a name was entered
      if (string.IsNullOrEmpty(name))
            throw new Exception("Valid name required");

      // TODO: insert a new person into the Person table
      result = await conn.InsertAsync(new Person { Name = name });

      StatusMessage = string.Format("{0} record(s) added [Name: {1})", result, name);
   }
   catch (Exception ex)
   {
      StatusMessage = string.Format("Failed to add {0}. Error: {1}", name, ex.Message);
   }
}

异步获取表中的所有项

最后,从数据库中异步检索“People”。

  1. 修改“GetAllPeople”方法,以使用异步调用返回结果。
public async Task<List<Person>> GetAllPeopleAsync()
{
   try
   {
      return await conn.Table<Person>().ToListAsync();
   }
   catch (Exception ex)
   {
      StatusMessage = string.Format("Failed to retrieve data. {0}", ex.Message);
   }

   return new List<Person>();
}

2.在“MainPage.xaml.cs”文件中,修改两个“Button.Click”事件处理程序,以使用“PersonRepository”类中的异步方法。 使用 async 和 await 关键字。

3.运行该程序,验证它是否仍能正常运行。

总结

在移动设备本地存储数据对于提高性能十分有用。 可以在本地存储重要数据并快速检索,而不是通过不断地调用远程服务器来获取数据。

可用的存储选项因拥有的数据类型而异。 处理本质上为关系数据的数据时,数据库是最佳选项。

可使用 SQLite 在 Xamarin 应用程序中创建本地数据库。 SQLite.NET 是 SQLite 的 C# 包装器。 它公开异步 API,以帮助确保应用程序的 UI 始终保持响应。

相关推荐

快递查询教程,批量查询物流,一键管理快递

作为商家,每天需要查询许许多多的快递单号,面对不同的快递公司,有没有简单一点的物流查询方法呢?小编的回答当然是有的,下面随小编一起来试试这个新技巧。需要哪些工具?安装一个快递批量查询高手快递单号怎么快...

一键自动查询所有快递的物流信息 支持圆通、韵达等多家快递

对于各位商家来说拥有一个好的快递软件,能够有效的提高自己的工作效率,在管理快递单号的时候都需要对单号进行表格整理,那怎么样能够快速的查询所有单号信息,并自动生成表格呢?1、其实方法很简单,我们不需要一...

快递查询单号查询,怎么查物流到哪了

输入单号怎么查快递到哪里去了呢?今天小编给大家分享一个新的技巧,它支持多家快递,一次能查询多个单号物流,还可对查询到的物流进行分析、筛选以及导出,下面一起来试试。需要哪些工具?安装一个快递批量查询高手...

3分钟查询物流,教你一键批量查询全部物流信息

很多朋友在问,如何在短时间内把单号的物流信息查询出来,查询完成后筛选已签收件、筛选未签收件,今天小编就分享一款物流查询神器,感兴趣的朋友接着往下看。第一步,运行【快递批量查询高手】在主界面中点击【添...

快递单号查询,一次性查询全部物流信息

现在各种快递的查询方式,各有各的好,各有各的劣,总的来说,还是有比较方便的。今天小编就给大家分享一个新的技巧,支持多家快递,一次能查询多个单号的物流,还能对查询到的物流进行分析、筛选以及导出,下面一起...

快递查询工具,批量查询多个快递快递单号的物流状态、签收时间

最近有朋友在问,怎么快速查询单号的物流信息呢?除了官网,还有没有更简单的方法呢?小编的回答当然是有的,下面一起来看看。需要哪些工具?安装一个快递批量查询高手多个京东的快递单号怎么快速查询?进入快递批量...

快递查询软件,自动识别查询快递单号查询方法

当你拥有多个快递单号的时候,该如何快速查询物流信息?比如单号没有快递公司时,又该如何自动识别再去查询呢?不知道如何操作的宝贝们,下面随小编一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号若干...

教你怎样查询快递查询单号并保存物流信息

商家发货,快递揽收后,一般会直接手动复制到官网上一个个查询物流,那么久而久之,就会觉得查询变得特别繁琐,今天小编给大家分享一个新的技巧,下面一起来试试。教程之前,我们来预览一下用快递批量查询高手...

简单几步骤查询所有快递物流信息

在高峰期订单量大的时候,可能需要一双手当十双手去查询快递物流,但是由于逐一去查询,效率极低,追踪困难。那么今天小编给大家分享一个新的技巧,一次能查询多个快递单号的物流,下面一起来学习一下,希望能给大家...

物流单号查询,如何查询快递信息,按最后更新时间搜索需要的单号

最近有很多朋友在问,如何通过快递单号查询物流信息,并按最后更新时间搜索出需要的单号呢?下面随小编一起来试试吧。需要哪些工具?安装一个快递批量查询高手快递单号若干怎么快速查询?运行【快递批量查询高手】...

连续保存新单号功能解析,导入单号查询并自动识别批量查快递信息

快递查询已经成为我们日常生活中不可或缺的一部分。然而,面对海量的快递单号,如何高效、准确地查询每一个快递的物流信息,成为了许多人头疼的问题。幸运的是,随着科技的进步,一款名为“快递批量查询高手”的软件...

快递查询教程,快递单号查询,筛选更新量为1的单号

最近有很多朋友在问,怎么快速查询快递单号的物流,并筛选出更新量为1的单号呢?今天小编给大家分享一个新方法,一起来试试吧。需要哪些工具?安装一个快递批量查询高手多个快递单号怎么快速查询?运行【快递批量查...

掌握批量查询快递动态的技巧,一键查找无信息记录的两种方法解析

在快节奏的商业环境中,高效的物流查询是确保业务顺畅运行的关键。作为快递查询达人,我深知时间的宝贵,因此,今天我将向大家介绍一款强大的工具——快递批量查询高手软件。这款软件能够帮助你批量查询快递动态,一...

从复杂到简单的单号查询,一键清除单号中的符号并批量查快递信息

在繁忙的商务与日常生活中,快递查询已成为不可或缺的一环。然而,面对海量的单号,逐一查询不仅耗时费力,还容易出错。现在,有了快递批量查询高手软件,一切变得简单明了。只需一键,即可搞定单号查询,一键处理单...

物流单号查询,在哪里查询快递

如果在快递单号多的情况,你还在一个个复制粘贴到官网上手动查询,是一件非常麻烦的事情。于是乎今天小编给大家分享一个新的技巧,下面一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号怎么快速查询?...

取消回复欢迎 发表评论: