.NET MAUI 本機資料庫

Browse sample. 流覽範例

SQLite 資料庫引擎可讓 .NET 多平臺應用程式 UI (.NET MAUI) 應用程式在共用程式碼中載入和儲存資料物件。 您可以遵循下列步驟,將 SQLite.NET 整合到 .NET MAUI 應用程式中,以在本機資料庫中儲存和擷取資訊:

  1. 安裝 NuGet 套件
  2. 設定常數
  3. 建立數據庫存取類別
  4. 存取數據
  5. 進階設定。

本文使用 sqlite-net-pcl NuGet 套件,為數據表提供 SQLite 資料庫存取權來儲存 todo 專案。 替代方法是使用 Microsoft.Data.Sqlite NuGet 套件,這是 SQLite 的輕量 型 ADO.NET 提供者。 Microsoft.Data.Sqlite 會針對連線、命令和數據讀取器等功能實作常見的 ADO.NET 抽象概念。

安裝 SQLite NuGet 套件

使用 NuGet 套件管理員來搜尋 sqlite-net-pcl 套件,並將最新版本新增至 .NET MAUI 應用程式專案。

有許多名稱類似的 NuGet 套件。 正確的套件有下列屬性:

  • 識別碼: sqlite-net-pcl
  • 作者: SQLite-net
  • 擁有者:praeclarum
  • NuGet 連結:sqlite-net-pcl

儘管套件名稱,但在 .NET MAUI 專案中使用 sqlite-net-pcl NuGet 套件。

重要

SQLite.NET 是 praeclarum/sqlite-net 存放庫所支援的第三方連結庫。

安裝SQLitePCLRaw.bundle_green

除了 sqlite-net-pcl 之外,您 暫時 還需要在每個平臺上安裝公開 SQLite 的基礎相依性:

  • 標識碼: SQLitePCLRaw.bundle_green
  • Version:>= 2.1.0
  • 作者: Eric Sink
  • 擁有者: Eric Sink
  • NuGet 連結:SQLitePCLRaw.bundle_green

設定應用程式常數

設定數據,例如資料庫檔名和路徑,可以儲存為應用程式中的常數。 範例專案包含 提供一般組態數據的 Constants.cs 檔案:

public static class Constants
{
    public const string DatabaseFilename = "TodoSQLite.db3";

    public const SQLite.SQLiteOpenFlags Flags =
        // open the database in read/write mode
        SQLite.SQLiteOpenFlags.ReadWrite |
        // create the database if it doesn't exist
        SQLite.SQLiteOpenFlags.Create |
        // enable multi-threaded database access
        SQLite.SQLiteOpenFlags.SharedCache;

    public static string DatabasePath =>
        Path.Combine(FileSystem.AppDataDirectory, DatabaseFilename);
}

在此範例中,常數檔案會指定用來初始化資料庫連接的預設 SQLiteOpenFlag 列舉值。 列舉 SQLiteOpenFlag 支援下列值:

  • Create:如果連接不存在,聯機會自動建立資料庫檔案。
  • FullMutex:連線是以串行化線程模式開啟。
  • NoMutex:連線是以多線程模式開啟。
  • PrivateCache:即使連線已啟用,連線也不會參與共用快取。
  • ReadWrite:連接可以讀取和寫入數據。
  • SharedCache:如果已啟用共用快取,連線將會參與共用快取。
  • ProtectionComplete:在鎖定裝置時,檔案會加密且無法存取。
  • ProtectionCompleteUnlessOpen:檔案會在開啟之前加密,但即使使用者鎖定裝置,仍可存取該檔案。
  • ProtectionCompleteUntilFirstUserAuthentication:檔案會在用戶開機並解除鎖定裝置之前加密。
  • ProtectionNone:資料庫檔案未加密。

您可能需要根據資料庫的使用方式來指定不同的旗標。 如需 的詳細資訊SQLiteOpenFlags,請參閱在 sqlite.org 上開啟新的資料庫 連線。

建立數據庫存取類別

資料庫包裝函式類別會從應用程式的其餘部分擷取數據存取層。 這個類別會集中查詢邏輯,並簡化資料庫初始化的管理,讓您在應用程式成長時更輕鬆地重構或擴充數據作業。 範例應用程式會為此目的定義類別 TodoItemDatabase

延遲初始化

使用 TodoItemDatabase 異步延遲初始化來延遲資料庫初始化,直到資料庫第一次存取為止,方法是使用類別中每個方法所呼叫的簡單 Init 方法:

public class TodoItemDatabase
{
    SQLiteAsyncConnection Database;

    public TodoItemDatabase()
    {
    }

    async Task Init()
    {
        if (Database is not null)
            return;

        Database = new SQLiteAsyncConnection(Constants.DatabasePath, Constants.Flags);
        var result = await Database.CreateTableAsync<TodoItem>();
    }
    ...
}

數據操作方法

類別 TodoItemDatabase 包含四種數據操作類型的方法:建立、讀取、編輯和刪除。 SQLite.NET 連結庫提供簡單的物件關係型對應 (ORM),可讓您儲存和擷取物件,而不需要撰寫 SQL 語句。

下列範例顯示範例應用程式中的數據操作方法:

public class TodoItemDatabase
{
    ...
    public async Task<List<TodoItem>> GetItemsAsync()
    {
        await Init();
        return await Database.Table<TodoItem>().ToListAsync();
    }

    public async Task<List<TodoItem>> GetItemsNotDoneAsync()
    {
        await Init();
        return await Database.Table<TodoItem>().Where(t => t.Done).ToListAsync();

        // 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();
    }

    public async Task<int> SaveItemAsync(TodoItem item)
    {
        await Init();
        if (item.ID != 0)
            return await Database.UpdateAsync(item);
        else
            return await Database.InsertAsync(item);
    }

    public async Task<int> DeleteItemAsync(TodoItem item)
    {
        await Init();
        return await Database.DeleteAsync(item);
    }
}

存取資料

如果您使用相依性插入,則可以 TodoItemDatabase 將 類別註冊為單一類別,以在整個應用程式中使用。 例如,您可以使用 和 AddTransient 方法,在 MauiProgram.csAddSingleton,將頁面和數據庫存取類別註冊為 物件上的IServiceCollection服務:

builder.Services.AddSingleton<TodoListPage>();
builder.Services.AddTransient<TodoItemPage>();

builder.Services.AddSingleton<TodoItemDatabase>();

然後,這些服務可以自動插入類別建構函式,並加以存取:

TodoItemDatabase database;

public TodoItemPage(TodoItemDatabase todoItemDatabase)
{
    InitializeComponent();
    database = todoItemDatabase;
}

async void OnSaveClicked(object sender, EventArgs e)
{
    if (string.IsNullOrWhiteSpace(Item.Name))
    {
        await DisplayAlert("Name Required", "Please enter a name for the todo item.", "OK");
        return;
    }

    await database.SaveItemAsync(Item);
    await Shell.Current.GoToAsync("..");
}

或者,也可以建立數據庫存取類別的新實例:

TodoItemDatabase database;

public TodoItemPage()
{
    InitializeComponent();
    database = new TodoItemDatabase();
}

如需 .NET MAUI 應用程式中相依性插入的詳細資訊,請參閱 相依性插入

進階設定

SQLite 提供強固的 API,其功能比本文和範例應用程式所涵蓋的功能還多。 下列各節涵蓋對於延展性而言很重要的功能。

如需詳細資訊,請參閱 sqlite.org 的 SQLite 檔

預先寫入記錄

根據預設,SQLite 會使用傳統的回復日誌。 未變更的資料庫內容複本會寫入個別的回復檔案,然後變更會直接寫入資料庫檔案。 刪除回復日誌時,就會發生 COMMIT。

預先寫入記錄 (WAL) 會先將變更寫入個別的 WAL 檔案。 在 WAL 模式中,COMMIT 是附加至 WAL 檔案的特殊記錄,可讓單一 WAL 檔案中發生多個交易。 WAL 檔案會在稱為 檢查點的特殊作業中,合併回資料庫檔案。

WAL 對於本機資料庫來說可能更快,因為讀取器和寫入器不會彼此封鎖,因此允許讀取和寫入作業同時運作。 不過,WAL 模式不允許變更 頁面大小、將其他檔案關聯新增至資料庫,以及新增額外的 檢查點 作業。

若要在 SQLite.NET 中啟用 WAL,請在 實體上SQLiteAsyncConnection呼叫 EnableWriteAheadLoggingAsync 方法:

await Database.EnableWriteAheadLoggingAsync();

如需詳細資訊,請參閱 SQLite 預先寫入記錄 sqlite.org。

複製資料庫

在某些情況下,可能需要複製 SQLite 資料庫:

  • 資料庫隨附於您的應用程式,但必須複製或移至行動裝置上的可寫入記憶體。
  • 您必須建立資料庫的備份或複本。
  • 您需要版本、移動或重新命名資料庫檔案。

一般而言,移動、重新命名或複製資料庫檔案的程式與任何其他檔類型的程式相同,但有一些其他考慮:

  • 嘗試移動資料庫檔案之前,應該先關閉所有資料庫連接。
  • 如果您使用 Write-Ahead 記錄,SQLite 會建立共用記憶體存取 (.shm) 檔案和 [寫入預先記錄] (.wal) 檔案。 請確定您也對這些檔案套用任何變更。