Delphi 行動應用程式開發中,資料儲存至關重要。本文以待辦事項應用程式為例,講解如何使用嵌入式 SQLite 資料函式庫和 FireDAC 進行資料管理。首先,我們將應用程式分為 UI、資料存取層和共用單元三個部分,降低耦合度,提高可維護性。接著,選擇 SQLite 作為嵌入式資料函式庫,並使用 FireDAC 建立資料函式庫連線。我們定義了 TToDo 記錄型別表示待辦事項,並使用 TToDos 泛型列表儲存多個待辦事項。為了抽象資料函式庫操作,我們設計了 IToDoData 介面,定義了 CRUD 操作方法。最後,我們示範瞭如何使用 FireDAC Connection Editor 建立資料函式庫表格,並在行動裝置上初始化資料函式庫連線和實作 IToDoData 介面,完成待辦事項應用程式的資料存取功能。
使用嵌入式資料函式庫建立待辦事項應用程式
在這一章中,我們將逐步建立一個簡單的行動應用程式,使用嵌入式資料函式庫來管理待辦事項列表。在開始編寫程式碼之前,讓我們先了解整體的應用程式架構。系統越複雜,正確的架構就越重要。
典型的開發方法是將大問題分解為較小、更容易解決的問題。在軟體開發中,最常見的方法是將整個系統分成明顯分離的層級。在資料驅動的應用程式中,我們至少可以識別出兩個邏輯部分:使用者介面(UI)和資料存取邏輯。清楚地分離這兩個層級可以實作外掛架構,讓 UI 能夠以標準方式連線到不同的資料存取模組,並且可以在不影響底層資料存取層的情況下替換 UI。
在 Delphi 應用程式的上下文中,我們可以將專案分成三個獨立的實體,如 圖 10.1 所示:
- 一個或多個視覺表單,用作圖形使用者介面(GUI)
- 一個或多個資料模組,包含非視覺元件,用於與資料函式庫互動
- 一個或多個獨立單元,包含通用型別和實用函式,供應用程式的兩個層級使用
圖 10.1:簡單資料函式庫應用程式的整體架構
此圖示展示了資料函式庫應用程式的基本架構,包括 UI、資料存取層以及共用單元。
圖表翻譯: 圖 10.1 展示了一個典型的三層架構,包括使用者介面、資料存取邏輯以及分享的通用單元。這種設計使得各層之間的耦合度降低,便於維護和擴充套件。
現在讓我們在 Delphi 中建立這個結構:
- 建立一個新的多裝置空白 Delphi 專案。將主表單單元另存為
uFormToDo,並將整個應用程式另存為ToDoList。將表單的Name屬性更改為FormToDo。 - 從 Delphi 主選單中選擇 檔案 | 新增 | 資料模組。將資料模組的
Name屬性更改為DMToDo,並將其另存為uDMToDo。 - 現在,從 Delphi 主選單中選擇 檔案 | 新增 | 單元,為專案新增一個空白單元。將其另存為
uToDoTypes。
現在,您應該擁有一個具有 圖 10.2 所示結構的專案。
圖 10.2:在 Delphi 中簡單資料函式庫應用程式的專案結構
此圖示展示了專案在 Delphi 中的組織結構,包括不同的單元和模組。
圖表翻譯: 圖 10.2 詳細展示了專案在 Delphi 中的檔案結構,包括主要的表單單元、資料模組以及共用的型別單元。
我們的專案由三個不同的單元組成,分別代表資料驅動應用程式的三個主要構建塊。現在,讓我們在這三個單元之間建立依賴關係。uToDoTypes 單元不依賴於專案中的其他單元,因此無需在其 uses 子句中新增任何內容。該單元需要被 UI 和資料存取邏輯同時使用。使用 檔案 | 使用單元 命令,將 uToDoTypes 單元新增到表單和資料模組的 interface 部分的 uses 子句中。
現在,將資料模組 uDMToDo 新增到主表單單元的 implementation 部分的 uses 子句中。這應該與 圖 10.1 中所示相符。
這是我們將在本章後續章節中繼續構建的應用程式的起點。在本文中,我們開始建立整體應用程式結構,並開始研究我們需要開發的每個區域。
建模資料
uToDoTypes 單元是用於新增在 UI 和資料存取模組之間共用的資料型別的。在本例中,我們需要定義一個代表待辦事項的型別。我們需要在記錄(record)和類別(class)之間做出選擇。記錄不需要擔心記憶體管理,通常效能優於物件。然而,將我們的“資料包裝器”型別定義為物件也是一個不錯的選擇。記錄型別不能被繼承,在更複雜的場景中,使用物件所帶來的靈活性可能使其比記錄更合適。
一個待辦事項應該具有哪些屬性?為了保持簡單,讓我們新增一個 Title 和一個 Category 字串欄位。在資料函式庫中,為任何給定的專案都有一個識別符號是很方便的,通常這是一個整數值。
以下是我們如何在 uToDoTypes 單元中表示待辦事項:
type
TToDo = record
Id: integer;
Title: string;
Category: string;
end;
TToDos = TList<TToDo>;
內容解密:
TToDo是一個記錄型別,用於表示單個待辦事項,包含Id、Title和Category三個欄位。TToDos是TToDo的泛型列表,用於儲存多個待辦事項,方便在資料模組中傳回所有待辦事項的列表。- 使用記錄型別可以避免手動管理記憶體,提高效能。
- 泛型列表提供了型別安全和便利的操作方法。
接下來的步驟是定義資料模組應該提供的標準操作。在資料函式庫領域,這通常被稱為 CRUD 操作。這個縮寫代表建立(Create)、讀取(Read)、更新(Update)和刪除(Delete)。由於我們的資料模型中只有一個實體,這些操作應該由四個不同的方法實作。我們還想新增第五個方法,即列出記錄的功能。
為了抽象這些操作,讓我們宣告一個新的介面型別,稱為 IToDoData,它將定義我們的資料模組應該提供的功能:
type
IToDoData = interface
function ToDoCreate(AValue: TToDo): Integer;
function ToDoRead(Id: Integer; out AValue: TToDo): Boolean;
function ToDoUpdate(AValue: TToDo): Boolean;
function ToDoDelete(Id: Integer): Boolean;
procedure ToDoList(AList: TToDos);
end;
內容解密:
IToDoData介面定義了對待辦事項進行 CRUD 操作的方法。ToDoCreate方法用於建立新的待辦事項,並傳回新專案的識別符號。ToDoRead方法根據給定的 ID 讀取待辦事項,並將其儲存在輸出的AValue引數中。ToDoUpdate方法用於更新現有的待辦事項。ToDoDelete方法根據給定的 ID 刪除待辦事項。ToDoList方法用於檢索所有待辦事項,並將其儲存在提供的TToDos列表中。
這是一種相當常見的表示 CRUD 操作的方式。透過定義這個介面,我們可以實作資料存取邏輯與 UI 的分離,使得我們的應用程式具有更好的可擴充套件性和維護性。
選擇資料函式庫的考量與實作
在開發行動應用程式時,資料儲存是一個至關重要的環節。大部分的行動應用程式都需要處理資料,若沒有適當的資料儲存方案,將會對應用程式的功能與使用者經驗造成影響。在設計應用程式時,開發者需要面對的首要架構決策之一就是選擇適當的資料儲存方式。
為何需要本地資料儲存?
雖然雲端儲存是目前的主流解決方案,但在缺乏網路連線的情況下,應用程式仍需要能夠正常運作並存取最新的資料。因此,在裝置上進行本地資料儲存是必要的。
簡易的資料儲存方案
在簡單的情況下,將資料儲存為純文字或二進位檔案是一種可行的方案。然而,對於更複雜的資料管理需求,嵌入式資料函式庫系統(embedded database system)通常是更好的選擇。
嵌入式資料函式庫的選擇
對於行動裝置上的Delphi應用程式,主要有兩種嵌入式資料函式庫可供選擇:
InterBase:由Embarcadero開發的SQL關聯式資料函式倉管理系統,具有輕量、自我調校和極少管理需求的特點。它支援多平台,並提供高效能和參照完整性。
- IBLite:免費的SQL引擎,資料函式庫檔案大小限制在100 MB以內,缺乏加密功能和Change Views支援。
- IBToGo:商業版的嵌入式InterBase,無資料函式庫大小限制,並提供強大的加密功能。
SQLite:一個屬於公共領域的關聯式資料函式庫引擎,已被整合到iOS和Android作業系統中。使用SQLite無需額外佈署資料函式庫引擎,因為應用程式可以在執行時動態建立資料函式庫和其結構。
使用FireDAC存取資料函式庫
FireDAC是Delphi中一個強大的資料存取函式庫,支援多種不同的資料函式庫引擎。對於本範例應用程式,我們將使用SQLite作為資料函式庫引擎,並透過FireDAC進行資料存取。
設定FireDAC連線到SQLite
- 將
TFDConnection元件拖曳到資料模組上,並將其Name屬性更改為FDConnToDos。 - 雙擊連線元件以顯示FireDAC Connection Editor視窗。選擇SQLite作為Driver ID,並輸入資料函式庫檔案的名稱。
資料表設計
我們的ToDo List應用程式將使用一個名為ToDos的資料表,該表包含以下欄位:
Id:整數型別的主鍵。Title和Category:文字欄位。
新增資料存取層
透過以下步驟將資料存取層新增至我們的範例應用程式:
- 設定
FDConnToDos連線元件以連線到SQLite資料函式庫。 - 使用查詢元件連線到資料函式庫連線,以執行SQL命令讀寫資料。
程式碼範例與解說
// 建立TFDConnection連線元件
FDConnToDos := TFDConnection.Create(nil);
// 設定連線引數
FDConnToDos.DriverName := 'SQLite';
FDConnToDos.Params.Database := 'ToDos.db';
FDConnToDos.Params.UserMode := dmManual;
// 開啟連線
FDConnToDos.Open;
內容解密:
- 上述程式碼建立了一個名為
FDConnToDos的TFDConnection例項,用於連線到SQLite資料函式庫。 - 設定
DriverName為'SQLite'以指定使用SQLite驅動程式。 - 透過
Params.Database屬性指定資料函式庫檔案名稱為'ToDos.db'。 Params.UserMode設定為dmManual以手動管理連線。- 最後呼叫
Open方法開啟資料函式庫連線。
在行動裝置上使用FireDAC存取SQLite資料函式庫
建立SQLite資料函式庫連線
要在行動裝置上使用SQLite資料函式庫,首先需要在Windows機器上建立一個SQLite資料函式庫檔案。為此,請在C:\Users\Public\Documents\目錄下建立一個名為ToDos.db的資料函式庫檔案。
- 無需輸入使用者名稱和密碼,所有預設引數值均可保留。預設的
OpenMode引數設定為CreateUTF8,這意味著資料函式庫檔案將在首次嘗試連線時自動建立。 - 點選
Test按鈕測試連線,如果連線成功,將在C:\Users\Public\Documents\資料夾中建立一個新的空SQLite資料函式庫檔案。
使用FireDAC Connection Editor
FireDAC Connection Editor是一個非常方便的工具。在第二個標籤頁中,有不同的選項可以控制FireDAC的工作方式。第三個標籤頁提供了有關資料函式庫連線的各種資訊。最後一個標籤頁稱為SQL Script,可以用於對已連線的資料函式庫執行任意SQL陳述式。
SQLite具有一個很好的SQL結構,CREATE TABLE IF NOT EXIST...,可以用於在開啟資料函式庫後直接建立資料函式庫表格。
建立ToDos資料函式庫表格
- 點選SQL Script標籤頁,並輸入以下程式碼以建立ToDos資料函式庫表格:
CREATE TABLE IF NOT EXISTS ToDos (
Id INTEGER NOT NULL PRIMARY KEY,
Title TEXT,
Category TEXT)
- 點選綠色箭頭按鈕執行查詢,如果查詢執行成功,將建立ToDos資料函式庫表格。
內容解密:
CREATE TABLE IF NOT EXISTS ToDos:如果ToDos表格不存在,則建立它。Id INTEGER NOT NULL PRIMARY KEY:建立一個名為Id的整數主鍵欄位,該欄位不能為空。Title TEXT和Category TEXT:建立兩個名為Title和Category的文字欄位。
將資料函式庫佈署到行動裝置
有兩種方法可以將資料函式庫佈署到行動裝置。可以使用Deployment Manager並將現有的資料函式庫檔案新增到要佈署的檔案清單中。另一種更簡單的方法是動態建立資料函式庫檔案和資料函式庫表格。
初始化資料函式庫連線
- 將連線元件的
LoginPrompt屬性設定為False。 - 在
OnBeforeConnect事件處理程式中,指定資料函式庫檔案的位置和名稱。
procedure TDMToDo.FDConnToDosBeforeConnect(Sender: Tobject);
begin
if IsMobilePlatform then
FDConnToDos.Params.Values['Database'] :=
TPath.Combine(TPath.GetDocumentsPath, 'ToDos.db');
end;
內容解密:
IsMobilePlatform:檢查是否在行動裝置上執行。TPath.Combine(TPath.GetDocumentsPath, 'ToDos.db'):取得行動裝置上的檔案目錄,並將資料函式庫檔案名稱與其結合。
- 在
OnAfterConnect事件處理程式中,建立ToDos表格如果它不存在。
procedure TDMToDo.FDConnToDosAfterConnect(Sender: Tobject);
const
SCreateTableSQL = 'CREATE TABLE IF NOT EXISTS ToDos ('
+ 'Id INTEGER NOT NULL PRIMARY KEY,'
+ 'Title TEXT, Category TEXT)';
begin
if IsMobilePlatform then
FDConnToDos.ExecSQL(SCreateTableSQL);
end;
內容解密:
SCreateTableSQL:定義建立ToDos表格的SQL陳述式。FDConnToDos.ExecSQL(SCreateTableSQL):執行SQL陳述式以建立ToDos表格。
實作IToDoData介面
- 將
IToDoData新增到TDMToDo類別宣告中,並複製介面方法的簽章到資料模組類別的公開區段。 - 按下Ctrl + Shift + C鍵組合以呼叫類別完成並產生空的方法實作。
新增TFDQuery元件
- 將六個TFDQuery元件拖曳到表單上,並分別將它們命名為FdqToDoMaxId、FdqToDoInsert、FdqToDoSelect、FdqToDoUpdate、FdqToDoDelete和FdqToDoSelectAll。
FireDAC元件在資料模組上的組態
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title 行動應用程式嵌入式資料函式庫實作
package "資料庫架構" {
package "應用層" {
component [連線池] as pool
component [ORM 框架] as orm
}
package "資料庫引擎" {
component [查詢解析器] as parser
component [優化器] as optimizer
component [執行引擎] as executor
}
package "儲存層" {
database [主資料庫] as master
database [讀取副本] as replica
database [快取層] as cache
}
}
pool --> orm : 管理連線
orm --> parser : SQL 查詢
parser --> optimizer : 解析樹
optimizer --> executor : 執行計畫
executor --> master : 寫入操作
executor --> replica : 讀取操作
cache --> executor : 快取命中
master --> replica : 資料同步
note right of cache
Redis/Memcached
減少資料庫負載
end note
@enduml圖表翻譯: 此圖示展示了TDMToDo資料模組與其上的FireDAC元件之間的關係,包括連線元件和多個查詢元件。
實作TDMToDo類別的方法
- 在FdqToDoMaxId查詢元件上雙擊,以顯示查詢編輯器視窗,並輸入查詢的SQL程式碼。
type
TDMToDo = class(TDataModule, IToDoData)
FdconnToDos: TFDConnection;
FdqToDoInsert: TFDQuery;
FdqToDoSelect: TFDQuery;
FdqToDoUpdate: TFDQuery;
FdqToDoDelete: TFDQuery;
FdqToDoSelectAll: TFDQuery;
FdqToDoMaxId: TFDQuery;
FDGUIxWaitCursor1: TFDGUIxWaitCursor;
procedure FdconnToDosBeforeConnect(Sender: TObject);
procedure FdconnToDosAfterConnect(Sender: TObject);
private
function IsMobilePlatform: Boolean;
function GetNewId: Integer;
public
// IToDoData
function ToDoCreate(AValue: TToDo): Integer;
function ToDoRead(Id: Integer; out AValue: TToDo): Boolean;
function ToDoUpdate(AValue: TToDo): Boolean;
function ToDoDelete(Id: Integer): Boolean;
procedure ToDoList(AList: TToDos);
end;
內容解密:
TDMToDo類別實作了IToDoData介面,提供了對ToDos資料函式庫表格的CRUD操作。IsMobilePlatform函式檢查是否在行動裝置上執行。GetNewId函式用於取得新的Id值。
本篇文章詳細介紹瞭如何使用FireDAC在行動裝置上存取SQLite資料函式庫,包括建立資料函式庫連線、建立資料函式庫表格、初始化資料函式庫連線以及實作IToDoData介面等步驟。透過這些步驟,開發者可以輕鬆地在行動裝置上使用SQLite資料函式庫,並進行相關的操作。