2012年10月19日 星期五

在以 C# 撰寫的 Metro 應用程式中使用 SQLite

使用 C++ 開發的開源資料庫 SQLite 其實已經支援 Windows Runtime 一段時間了,
但從原始碼編譯出 dll 的過程有不少難關要突破,一位在微軟工作的大大提供了編譯流程的影片,
請參考:http://timheuer.com/blog/archive/2012/06/05/howto-video-using-sqlite-in-metro-style-app.aspx

幸好,現在 NuGet 已經可以幫我們解決編譯的所有流程了,
如果不想自己走一遍上述的流程,可以利用 NuGet 安裝 SQLite for Windows Runtime
並且在 Windows 擴充功能中選擇以下兩項參考加入至專案中:
在專案加入此參考:Microsoft Visual C++ Runtime Package
使用工具、擴充功能及更新加入:SQLite for Windows Runtime
如果你的應用程式是使用 C# 或 VB 這種受到 CLR 所管理的語言來開發,
那就還需要安裝以 managed code 所開發的程式庫才能使用,
目前沒什麼選項可以選擇,雖然 NuGet 上面看到很多 sqlite 相關的套件,
但只有 sqlite-net 是針對 managed code 所開發的,
其他的套件想裝也裝不起來,所以請再使用 NuGet 安裝 sqlite-net 套件,
在你的專案安裝完後多了 SQLite.cs、SQLiteAsync.cs 這兩個檔案時,就可以使用了。

詳細的步驟可以參考剛才那位大大的 Blog 另一篇文章
http://timheuer.com/blog/archive/2012/08/07/updated-how-to-using-sqlite-from-windows-store-apps.aspx

如果你是曾經在 Windows Phone 上使用過 C# Sqlite for WP7,
並且很習慣使用傳統以字串組合成 SQL 指令再利用 SQLiteCommand 執行的用戶,
那在使用 sqlite-net 的一開始大概需要一些綀習才可以上手操作這個程式庫,
原因是,雖然 sqlite-net 也可以執行 SQL 指令字串,但僅限於 Insert、Update、Delete,
它並沒有以前常用的 SqliteDataReader 類別,也沒有 ExecuteReader 方法,
sqlite-net 對資料表的查詢方式僅提供 ORM 的語法,這真的需要一些學習與習慣的時間,
以下使用傳統指令的方式,與 ORM 的方式示範如何在 WinRT 下使用 C# 操作 SQLite

建立一個對應資料表結構的類別,並以 Properties 對應欄位型別,
public class member
{
    [PrimaryKey, AutoIncrement]
    public int id { get; set; }
    public string name { get; set; }
}

利用兩種不同的方式建立、操作 member table
private void OnSqliteDemoButtonClick(object sender, RoutedEventArgs e)
{
    String strDBPath = Path.Combine(ApplicationData.Current.LocalFolder.Path, "company.db");
    SQLiteConnection conn = new SQLiteConnection(strDBPath);
   
    // 以 SQL 指令產生資料表
    SQLiteCommand cmdCreateTable = conn.CreateCommand("CREATE TABLE IF NOT EXISTS member (id INTEGER PRIMARY KEY, name TEXT NOT NULL)");
    cmdCreateTable.ExecuteNonQuery();

    // 以 SQL 指令新增資料
    String strName = "Ascii";
    SQLiteCommand cmdInsert = conn.CreateCommand("INSERT INTO member (name) VALUES (?)", strName);
    cmdInsert.ExecuteNonQuery();

    // 以 SQL 指令修改資料
    SQLiteCommand cmdUpdate = conn.CreateCommand("UPDATE member SET name = ? WHERE name = ?", "Benjamin", "Ascii");
    cmdUpdate.ExecuteNonQuery();

    // 以 ORM 方式產生資料表、新增資料
    conn.CreateTable(typeof(member)); // 預設為 IF NOT EXISTS
    conn.Insert(new member() { name = "Benjamin" });

    // 以 ORM 方式查詢資料表
    int memberCount = conn.ExecuteScalar<int>("SELECT COUNT(*) FROM member"); // memberCount = 2
    List<member> memberList = conn.Query<member>("SELECT * FROM member"); // memberList.Count = 2

    // 以 ORM 方式修改欄位
    TableQuery<member> queryToUpdate = conn.Table<member>().Where(v => (v.name == "Benjamin"));
    member memUpdate = queryToUpdate.ElementAt(0);
    memUpdate.name = "Ascii";
    conn.Update(memUpdate);

    // 以 ORM 方式刪除資料列
    TableQuery<member> queryToDelete = conn.Table<member>().Where((v) => (v.name == "Benjamin" || v.name == "Ascii"));
    foreach (member m in queryToDelete)
    {
        conn.Delete<member>(m.id);
    }
    // 全部執行完,資料表內容被清空嘍
}

沒有留言:

張貼留言