在应用中使用数据

DataAccess_Adv示例显示了工作应用程序,它支持用户输入和 CRUD (创建、读取、更新和删除)数据库功能。 该应用程序包括两个屏幕:列表和数据输入窗体。 所有数据访问代码在 iOS 和 Android 中均可重用,无需修改。

添加一些数据后,应用程序屏幕在 Android 上的外观如下所示:

Android sample list

Android sample detail

Android 项目如下所示 - 本部分中显示的代码包含在Orm目录中:

Android project tree

Android 中活动的本机 UI 代码超出本文档的范围。 有关 UI 控件的详细信息,请参阅Android ListViews 和适配器指南。

读取

示例中存在几个读取操作:

  • 读取列表
  • 读取单个记录

StockDatabase 类中的两种方法是:

public IEnumerable<Stock> GetStocks ()
{
    lock (locker) {
        return (from i in Table<Stock> () select i).ToList ();
    }
}
public Stock GetStock (int id)
{
    lock (locker) {
        return Table<Stock>().FirstOrDefault(x => x.Id == id);
    }
}

Android 将数据呈现为ListView

创建和更新

为了简化应用程序代码,提供了一个保存方法来执行插入或更新,具体取决于是否已设置 PrimaryKey。 由于该 Id 属性使用 [PrimaryKey] 属性进行标记,因此不应在代码中设置该属性。 此方法将检测之前是否已保存值(通过检查主键属性)并相应地插入或更新对象:

public int SaveStock (Stock item)
{
    lock (locker) {
        if (item.Id != 0) {
            Update (item);
            return item.Id;
    } else {
            return Insert (item);
        }
    }
}

实际应用程序通常需要一些验证(例如必填字段、最小长度或其他业务规则)。 良好的跨平台应用程序可在共享代码中尽可能多地实现验证逻辑,从而根据平台的功能将验证错误传回 UI 以进行显示。

删除

Insert 方法和 Update 方法不同,该 Delete<T> 方法只能接受主键值而不是完整的 Stock 对象。 在此示例中,Stock 对象将传递到方法中,但仅向 Delete<T> 方法传递 Id 属性。

public int DeleteStock(Stock stock)
{
    lock (locker) {
        return Delete<Stock> (stock.Id);
    }
}

使用预填充的 SQLite 数据库文件

一些应用程序随已填充数据的数据库一起提供。 在移动应用程序中,可以轻松完成此操作,方法是将现有的 SQLite 数据库文件与应用一起提供,并将其复制到可写目录,然后再访问它。 由于 SQLite 是许多平台上使用的标准文件格式,因此可以使用许多工具创建 SQLite 数据库文件:

  • SQLite Manager Firefox 扩展 - 适用于 Mac 和 Windows,并生成与 iOS 和 Android 兼容的文件。

  • 命令行 - 请参阅www.sqlite.org/sqlite.html

创建数据库文件以便与应用一起分发时,请注意表和列的命名,以确保它们与代码预期匹配,尤其是在使用预期名称与 C# 类和属性(或关联的自定义属性)相匹配的 SQLite.NET 时。

要确保一些代码在 Android 应用的任何其他代码之前运行,可以将它放置在第一个要加载的活动中,也可以创建在任何活动之前加载的Application子类。 下面的代码显示了Application子类,该子类将现有数据库文件data.sqlite复制到/Resources/Raw/目录中。

[Application]
public class YourAndroidApp : Application {
    public override void OnCreate ()
    {
        base.OnCreate ();
        var docFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
        Console.WriteLine ("Data path:" + Database.DatabaseFilePath);
        var dbFile = Path.Combine(docFolder, "data.sqlite"); // FILE NAME TO USE WHEN COPIED
        if (!System.IO.File.Exists(dbFile)) {
            var s = Resources.OpenRawResource(Resource.Raw.data);  // DATA FILE RESOURCE ID
            FileStream writeStream = new FileStream(dbFile, FileMode.OpenOrCreate, FileAccess.Write);
            ReadWriteStream(s, writeStream);
        }
    }
    // readStream is the stream you need to read
    // writeStream is the stream you want to write to
    private void ReadWriteStream(Stream readStream, Stream writeStream)
    {
        int Length = 256;
        Byte[] buffer = new Byte[Length];
        int bytesRead = readStream.Read(buffer, 0, Length);
        // write the required bytes
        while (bytesRead > 0)
        {
            writeStream.Write(buffer, 0, bytesRead);
            bytesRead = readStream.Read(buffer, 0, Length);
        }
        readStream.Close();
        writeStream.Close();
    }
}