将 SQLite.NET 与 Xamarin.iOS 配合使用

Xamarin 推荐的 SQLite.NET 库是一个基本的 ORM,可让你在 iOS 设备上的本地 SQLite 数据库中存储和检索对象。 ORM 是对象关系映射的英文缩写,它是一个 API,可让你在数据库中保存和检索“对象”,而无需编写 SQL 语句。

使用情况

若要将 SQLite.NET 库包含在 Xamarin 应用中,请将以下 NuGet 包添加到项目:

SQLite.NET NuGet 包

有许多不同的 SQLite 包可供使用 - 请务必选择正确的一个(它可能不是搜索中排名最靠前的结果)。

重要

SQLite.NET 是 praeclarum/sqlite-net 存储库支持的第三方库。

获得可用的 SQLite.NET 库后,请按照以下三个步骤使用它来访问数据库:

  1. 添加 using 语句 - 将以下语句添加到需要数据访问的 C# 文件中

    using SQLite;
    
  2. 创建空白数据库 - 可以通过将文件路径传递给 SQLiteConnection 类构造函数来创建数据库引用。 无需检查文件是否已存在 - 如果需要,它将自动创建,否则将打开现有的数据库文件。

    var db = new SQLiteConnection (dbPath);
    

    应根据本文档前面讨论的规则确定 dbPath 变量。

  3. 保存数据 - 创建 SQLiteConnection 对象后,将通过调用其方法(例如 CreateTable 和 Insert)来执行数据库命令,如下所示

    db.CreateTable<Stock> ();
    db.Insert (newStock); // after creating the newStock object
    
  4. 检索数据 - 要检索对象(或对象列表),请使用以下语法

    var stock = db.Get<Stock>(5); // primary key id of 5
    var stockList = db.Table<Stock>();
    

基本数据访问示例

在 iOS 上运行时,本文档的 DataAccess_Basic 示例代码如下所示。 该代码演示如何执行简单的 SQLite.NET 操作,并在应用程序的主窗口中以文本形式显示结果。

iOS

iOS SQLite.NET 示例

以下代码示例演示了使用 SQLite.NET 库封装基础数据库访问的整个数据库交互。 该示例演示了以下操作:

  1. 创建数据库文件
  2. 通过创建对象来插入一些数据,然后保存它们
  3. 查询数据

需要包含这些命名空间:

using SQLite; // from the github SQLite.cs class

这要求将 SQLite 添加到项目中,如此处突出显示的那样。 请注意,SQLite 数据库表是通过向类(Stock 类)添加属性而不是通过 CREATE TABLE 命令来定义的。

[Table("Items")]
public class Stock {
    [PrimaryKey, AutoIncrement, Column("_id")]
    public int Id { get; set; }
    [MaxLength(8)]
    public string Symbol { get; set; }
}
public static void DoSomeDataAccess () {
       Console.WriteLine ("Creating database, if it doesn't already exist");
   string dbPath = Path.Combine (
        Environment.GetFolderPath (Environment.SpecialFolder.Personal),
        "ormdemo.db3");
   var db = new SQLiteConnection (dbPath);
   db.CreateTable<Stock> ();
   if (db.Table<Stock> ().Count() == 0) {
        // only insert the data if it doesn't already exist
        var newStock = new Stock ();
        newStock.Symbol = "AAPL";
        db.Insert (newStock);
        newStock = new Stock ();
        newStock.Symbol = "GOOG";
        db.Insert (newStock);
        newStock = new Stock ();
        newStock.Symbol = "MSFT";
        db.Insert (newStock);
    }
    Console.WriteLine("Reading data");
    var table = db.Table<Stock> ();
    foreach (var s in table) {
        Console.WriteLine (s.Id + " " + s.Symbol);
    }
}

使用 [Table] 属性而不指定表名称参数将导致基础数据库表与类具有相同的名称(在本例中为“Stock”)。 如果直接针对数据库编写 SQL 查询而不是使用 ORM 数据访问方法,则实际的表名称非常重要。 同样,[Column("_id")] 特性是可选的,如果不存在,将向表中添加与类中的属性同名的列。

SQLite 特性

可应用于类以控制它们在基础数据库中的存储方式的常见属性包括:

  • [PrimaryKey] – 可以将此属性应用于整数属性,以强制其成为基础表的主键。 不支持复合主键。
  • [AutoIncrement] – 此属性将导致整数属性的值针对插入数据库的每个新对象自动递增
  • [Column(name)] – name 参数设置基础数据库列的名称。
  • [Table(name)] - 将类标记为能够存储在具有指定名称的基础 SQLite 表中
  • [MaxLength(value)] – 尝试执行数据库插入时限制文本属性的长度。 使用代码应在插入对象之前验证此属性,因为仅在尝试数据库插入或更新操作时才会“检查”此属性。
  • [Ignore] – 导致 SQLite.NET 忽略此属性。 这对于具有无法存储在数据库中的类型的属性,或者对无法自动解析为 SQLite 的集合建模的属性特别有用。
  • [Unique] – 确保基础数据库列中的值是唯一的。

其中大多数特性都是可选的。 始终应该指定整数主键,以便可以对数据高效执行选择和删除查询。

更复杂的查询

SQLiteConnection 中的以下方法可用于执行其他数据操作:

  • Insert - 将新对象添加到数据库中
  • Get<T> - 尝试使用主键检索对象
  • Table<T> - 返回表中的所有对象。
  • Delete – 使用主键删除对象
  • Query<T> - 执行返回多行(作为对象)的 SQL 查询。
  • Execute – 当你不希望从 SQL(例如 INSERT、UPDATE 和 DELETE 指令)返回行时,请使用此方法(而不是 Query)。

按主键获取对象

SQLite.Net 提供了 Get 方法来根据主键检索单个对象。

var existingItem = db.Get<Stock>(3);

使用 Linq 选择对象

返回集合的方法支持 IEnumerable<T>,因此可以使用 Linq 对表的内容进行查询或排序。 以下代码演示了使用 Linq 筛选掉以字母“A”开头的所有条目的示例:

var apple = from s in db.Table<Stock>()
    where s.Symbol.StartsWith ("A")
    select s;
Console.WriteLine ("-> " + apple.FirstOrDefault ().Symbol);

使用 SQL 选择对象

尽管 SQLite.Net 可以提供对数据的基于对象的访问,但有时你可能需要执行比 Linq 允许的查询更复杂的查询(或者可能需要更快的性能)。 可以将 SQL 命令与 Query 方法结合使用,如下所示:

var stocksStartingWithA = db.Query<Stock>("SELECT * FROM Items WHERE Symbol = ?", "A");
foreach (var s in stocksStartingWithA) {
    Console.WriteLine ("a " + s.Symbol);
}

重要

直接编写 SQL 语句时,将会创建对数据库中表和列的名称的依赖关系,这些名称是从类及其属性生成的。 如果在代码中更改这些名称,请务必记得更新所有手动编写的 SQL 语句。

删除对象

主键用于删除行,如下所示:

var rowcount = db.Delete<Stock>(someStock.Id); // Id is the primary key

可以检查 rowcount 以确认有多少行受到影响(在本例中为已删除)。

结合多个线程使用 SQLite.NET

SQLite 支持三种不同的线程模式:单线程、多线程和序列化。 如果你希望不受任何限制地从多个线程访问数据库,可以将 SQLite 配置为使用序列化线程模式。 在应用程序中尽早设置此模式非常重要(例如,在 OnCreate 方法的开头)。

若要更改线程模式,请调用 Mono.Data.Sqlite 命名空间中的 SqliteConnection.SetConfig。 例如,此代码行将 SQLite 配置为“序列化”模式

using Mono.Data.Sqlite;
...
SqliteConnection.SetConfig(SQLiteConfig.Serialized);