2013年3月12日 星期二

在 C# WP8 專案中建立 Local DataBase 的幾種選擇

在 Windows Phone 7 的時代,想建立 Local DataBase 的方法除了使用官方的 LINQ to SQL 之外,還有另外兩個比較多人選擇的開源套件分別是

Sqlite Client for Windows Phone
C# Sqlite For WP7

兩個開源套件都是根據 C# SQLite 專案所改寫的:C#-SQLite
同時這兩個開源套件所提供的介面皆是傳統的 ExecuteReader、ExecuteNonQuery、ExecuteScalar 這種直接執行 SQL 指令字串的方式,深得我心,但其實我個人比較喜歡 C# Sqlite For WP7 這個套件,因為它可以在 NuGet 中找到,但在 C# Sqlite For WP7 的作者 CodePlex 頁面上寫道:
NOTE: This project was a solution long before Windows Phone have built-in Database Support. You should be using Local Database support provided by Windows Phone itself!
看起來作者其實是比較建議 WP 的開發者能夠使用 Windows Phone 官方的 LINQ to SQL:

Local Database Overview for Windows Phone
Create a Basic Local Database Application for Windows Phone

但 LINQ to SQL 的方式本來就是純 ORM 的操作概念,在使用上會有一種專案中的類別大都需要根據 DB Table 的結構來定義的限制感,再加上 Windows Phone SDK 中的 LINQ 又是醃割過的,提供的 Method 更少,總之我個人的感覺就是難用,所以一直以來都還是使用 C# Sqlite For WP7

在 Windows Phone 8 之後,因為作業系統核心的改變,真正官方的 SQLite 終於有機會在 WP8 的專案上使用了,使用方法和在 Windows Runtime 上面使用非常相似,在 Visual Studio 2012 的工具、擴充功能及更新找到 SQLite for Windows Phone 並且安裝它,或是在 SQLite Download Page 找到 Precompiled Binaries for Windows Phone 8 下載 sqlite-wp80-winrt-3071502.vsix 檔案並且安裝它也可以。

安裝成功並且重新啟動過 Visual Studio 後,在專案上按加入參考後開啟參考管理員(Reference),在裡面 Windows Phone 分類中的擴充功能(Extensions)即會出現新的選項 SQLite for Windows Phone,請勾選使用。

因為此 Extension 是由 C++ 所開發的,所以使用了 SQLite for Windows Phone 後在編譯專案時,必須選擇編譯 ARM 或 x86 的平台版本,無法編譯 Any CPU 的版本,此點和在 C# 的 WinRT 專案上使用 SQLite 是一樣的狀況,當然我們也需要安裝 sqlite-net 來提供介面,但透過 NuGet 安裝 sqlite-net 之後,會發現在編譯時被提示 Community.CsharpSqlite.Sqlite3 無法參考,我們看一下原因,可以發現在 SQLite.cs 最上面有幾行字:

#if WINDOWS_PHONE && !USE_WP8_NATIVE_SQLITE
#define USE_CSHARP_SQLITE
#endif

這裡的 USE_CSHARP_SQLITE 指的我猜應該是上面所說到的 C#-SQLite 專案,但這個專案並不是 SQLite 官方在維護的版本,所以我們還是使用剛才在擴充套件中安裝的 SQLite for Windows Phone 才比較有保障,而想要使用 SQLite 還必須再參考一下此專案:sqlite-net-wp8

在專案中的 ReadMe 中有提到使用 sqlite-net-wp8 的步驟,大致下就是將此專案由 git clone 回來後加到我們的 solution 中,並且在使用到 sqlite-net 的專案中加入 USE_WP8_NATIVE_SQLITE 這個 symbol 即可。

SQLite 的使用方法因為都是 sqlite-net 所以介面都是一樣的,可以參考 Windows Runtime 的記錄:在以 C# 撰寫的 Metro 應用程式中使用 SQLite

但在這裡還是再記錄一些新學到的技巧,我在剛開始使用 ORM 時其實有苦惱一下 class 的命名該以資料列的角度來命名,還是以表格的角度來命名,以購物車表格 (shopping_cart_table) 為例,我們通常會定義一個類別來綁定該表格的各欄位,並以此類別來做為 CreateTable 的參數,例如

public class Item
{
    [PrimaryKey, AutoIncrement]
    public int id { get; set; }
    public string name { get; set; }
}

conn.CreateTable(typeof(Item));

此時會建立一個名為 Item 的 Table,並且裡面有兩個欄位分別是 id、name,這就是以資料列的角度來命名,有一點奇怪,這個表格怎樣也不該叫作 Item 呀,要也是叫作 Items 或 ItemTable 但若是把類別取名叫作 ShoppingCartTable,如此我們在 Query 時就會拿到一個 List<ShoppingCartTable> 的結構,也是很奇怪,其於這種奇怪的狀況下又再去 Trace sqlite-net 中的程式碼,發現內部其實有實作讀取類別的 Attribute 來讓開發勢自行定義表格及欄位名稱,如此我們就可以很沒有其他顧慮的將類別以資料列的角度來命名,例如

[Table("shopping_cart_table")]
public class Item
{
    [PrimaryKey, AutoIncrement, Column("id")]
    public int ItemId { get; set; }
    [Column("name")]
    public string ItemName { get; set; }
}

conn.CreateTable(typeof(Item));

此時即建立名為 shopping_cart_table 的表格,有 id、name 兩個欄位,且與 Item 類別做綁定

1 則留言: