簡單記錄一下大家最常用 SQLite.net 與它 Dependency 的 SQLitePCLRaw NuGet package 的搭配使用
首先我相信寫 UWP 會用到 SQLite 除了使用微軟官方的 Microsoft.Data.Sqlite / EFCore 外,應該最常用的是"老牌"的 SQLite.net 這個 NuGet package 了吧!
而且 SQLite.net 的"壽命"應該比微軟的更為久,畢竟一開始印象中官方是沒有 SQLite 的 Data Provider 尤其在 Windows Phone / WinRT 上
並且 SQLite.net 也提供了簡單的 ORM 的框架,方便開發者使用,所以大家都很開心的使用著~
前一陣子因為某些原因,我們是自己複製了 SQLite.net 的原始碼,但是依照它的方式編譯,然後發現它的"底層"在某個版本之後依賴了一個 NuGet Package,叫 SQLitePCL.raw,
而 SQLitePCL.raw 這個 NuGet package 在從 SQLite.net 開始依賴它後其實也改版了幾次,在 1.0 版之後有一些比較大的改變,然後在 SQLitePCL.raw 的 Github page 的 readme.md 有些複雜,
花了點時間閱讀然後並且自己實測後,有了點心得所以紀錄一下。
SQLite.net 的 GitHub 網址:https://github.com/praeclarum/sqlite-net
SQLitePCL.raw 的 GitHub 網址:https://github.com/ericsink/SQLitePCL.raw
先來簡單說一下這兩個 NuGet package 的關係:
- SQLitePCL.raw 簡單來看其實就是 wrapper (P/Invoke) 平台相關的 sqlite3.dll 成為 managed code 的"介接層",但是 API 的樣子基本上 follow 原來 sqlite3 提供的 API 的樣子。
- SQLite.net 就是再把 SQLitePCL.raw 提供的再包裝了一層,看起來比較像 ADO.NET 的樣子,並且也提供了簡單的 ORM 層。
不過一開始的 SQLite.net 在沒有依賴 SQLitePCL.raw 的時候, P/Invoke 那段是自己做的,目前的原始碼也是有保留著 P/Invoke 那段,所以如果自己使用原始碼編譯 SQLite.net 的話,是可以去除掉 SQLitePCL.raw 的依賴的。不過我想原作者想依賴 SQLitePCL.raw 的想法應該就是有人在做一樣的事情就不需要自己在做,並且 SQLitePCL.raw 還有持續再更新,那就不要自己浪費力氣做。
下面的內容是自己會編譯 SQLite.net 情況下,不會的話,其實客制化這些搭配應該是沒有意義。
- SQLitePCL.raw 是可以單獨使用的,如果你是想直接使用 sqlite3 API 的話(C style API)
- SQLitePCL.raw 的作者好像也有自己包裝了幾個比較 high level 的 NuGet package
- 要能夠使用 SQLitePCL.raw 最起碼要使用下列前 2 個 NuGet package,第 3 個則是看情況
- SQLitePCLRaw.core :包裝好的抽象API層
- SQLitePCLRaw.provider_xxxx :P/Invoke 層,不同的 provider 就是針對不同的 sqlite3 函示庫去寫 P/Invoke,因為 P/Invoke 的時候需要指定你要 Invoke 的 dll 名稱,所以可以看它 NuGet Package 的名稱就知道使用的是哪一個。
- 例如 provider.e_sqlite 就是使用它自己編譯的 e_sqlite3.dll,provider.sqltie3 就是使用 sqlite 官方的 sqlite3.dll,provider.winsqlite 就是使用微軟在 windows 10 14393 後內建在系統中的 winsqlite3.dll
- 使用 provider.sqlite3 的時候,記得自己在 project 要加好 reference,不然你部屬的時候不會出現 sqlite3.dll,然後程式一跑就會因為要 P/Invoke 的時候找不到 sqlite3.dll 然後就挫賽了
- 也支援你自己編譯的 sqlite 喔~不過記得命名要對,不然 P/Invoke 不到一樣挫賽,至於命名是啥可以翻 SQLitePCLRaw 的原始碼
- SQLitePCLRaw.lib_xxxx:"真正"的 sqlite3.dll ,簡單來說就是 C 寫的 native code,之所以說不是必要的就是因為看你使用的 provider,如果使用的是一些內建在系統或自己 reference 的dll,就不一定要加入這個 NuGet
- 大家最常使用到的應該是 e_sqlite 的這個,這個其實是作者自己編譯的 sqlite3.dll,GitHub 的原始碼裡面可以看到它其實有一份 sqlite 的原始碼,編譯後的名稱就叫 e_sqlite3.dll,用這個的好處是你不需要自己修改 project 檔案讓不同 CPU reference 到對應的 sqlite3.dll,當然 UWP 沒有這個困擾,因為 sqlite 官方有提供 vsix ,它會依照 CPU 幫你部屬,不過如果你寫 .NET 的話就比較麻煩一點
- 所以 SQLitePCL.raw 作者為了大家方便再建立了一個叫 SQLiteRaw.bundle_xxxx 的 NuGet package,讓你不用管那麼多,使用 budle 的就會自動依照你 project 的平台使用正確的 package 了,一般情況下使用這個就好了,有興趣可以去 NuGet 網站或 NuGet package manager 去看下你使用的 SQLiteRaw.bundle_xxx 所依賴的是哪一些 NuGet package ,就可以知道你安裝到的究竟是哪一個 provider_xxxx 和哪一個 lib_xxxx
- 最常用的應該是 SQLite.raw.bundle_green 這個,這個也是 SQLite.net 所依賴的 NuGet package,而這個使用的就是作者自己編譯的 e_sqlite3.dll
- 如果你的 App 使用了 SQLite.raw.bundle_gree 的 NuGet package 其實不需要自己再去 reference sqlite 官方的 dll ,沒有意義,因為 P/Invoke 層那邊去 invoke 的就是 e_sqlite3.dll 不會是官方的 sqlite3.dll
- 針對 UWP 可以使用的搭配有
- 快樂使用 SQLite.raw.bundle_green (SQLiteRaw.core + SQLiteRaw.provider.e_sqlite + SQLitePCLRaw.lib.e_sqlite) 啥都不用管就可以跑了
- 好處:啥都不用管
- 壞處:sqlite3 函示庫的版本不會是最新的,而是當時 NuGet 上架時候作者自己編譯的版本
- 使用 SQLitePCLRaw.core + SQLitePCLRaw.provider.sqlite3.uwp10 + 加入安裝 sqlite 官方的 vsix 後的 sqlite reference
- 需要把 SQLite.net project 重新建立為 UWP 的而不是原先的 PCL
- 需要修改 SQlite.cs 的原始碼,把 static SQLiteConnectoin 的 SQLitePCL.Batteries_V2.Init(); 換成 SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_sqlite3());
- 為什麼知道要換成這個,因為去翻 SQLitePCL.raw 的原始碼,看 SQLitePCL.Batteries_V2.Init(); 這個 method 裡面怎麼寫的就知道了
- 好處:sqlite3 函示庫可以隨 sqlite 官方更新而更新
- 壞處:換 sqlite3 版本的時候,大家都要換,不然其他人會編譯不過
- 使用 SQLitePCLRaw.bundle_winsqlite3(其實就是 SQLitePCLRaw.core + SQLitePCLRaw.provider_winsqlite3)
- 需要把 SQLite.net project 重新建立為 UWP 的而不是原先的 PCL
- 好處:用的是微軟自己編譯的 sqlite
- 壞處:用的是微軟自己編譯的 sqlite (? XD) 不會是最新的 sqltie3
- 快樂使用 SQLite.raw.bundle_green (SQLiteRaw.core + SQLiteRaw.provider.e_sqlite + SQLitePCLRaw.lib.e_sqlite) 啥都不用管就可以跑了
- 自己產生 SQLite.net 的 project 的時候,注意原來的 project 在 build 的 conditional compiation symbol 喔!不然你會編譯到不是你想要的程式碼 XD 當初沒注意被搞過 XD
- 如果你開發 Xamarin 的話,搭配的概念也是類似的,可以參考
以上~ 有任何錯誤請多多指教~
一開始沒搞清楚的時候,我們就是用了 SQLitePCLRaw.bundle_green 然後還自己 refernce sqlite 官方的 dll,然後 sqlite 官方改版我們也更新的很開心,殊不知一切都是白工 XD
PS : 其實嘗試過 SQLite.net 一樣使用 bundle_green 但是 app 是使用 bundle_winsqlite3 但是卻不能執行,但我不確定是不是那時候發生了什麼事情或是那邊沒搞好,所以你也可以再玩玩看不同的搭配法。