その3 で終わったつもりだったのですが、追加情報です。 (シリーズ一覧)
ソースコードは GitHub で公開しています。
git リポジトリ:https://github.com/yumimatoba14/SQLiteTest.git
7. e_sqlite3.dll が見つからない問題
その1 では e_sqlite3.dll が bin フォルダにコピーされない問題をビルド後イベントでコピーすることで対応しましたが、ちょっとだけスマートな方法を発見したのでご紹介。
<Project Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\Microsoft.EntityFrameworkCore.Design.3.1.32\build\net461\Microsoft.EntityFrameworkCore.Design.props" Condition="Exists('..\packages\Microsoft.EntityFrameworkCore.Design.3.1.32\build\net461\Microsoft.EntityFrameworkCore.Design.props')" />
... 以下の行を追加
<Import Project="..\packages\SQLitePCLRaw.lib.e_sqlite3.2.1.2\buildTransitive\net461\SQLitePCLRaw.lib.e_sqlite3.targets" Condition="Exists('..\packages\SQLitePCLRaw.lib.e_sqlite3.2.1.2\buildTransitive\net461\SQLitePCLRaw.lib.e_sqlite3.targets')" />
...
</Project>
要するに packages フォルダに存在するファイル SQLitePCLRaw.lib.e_sqlite3.targets を csrpoj にインポートしています。 csproj の書式を理解していないので正しい操作であるかは不明なのですが...
build フォルダではなく buildTransitive フォルダに置いているところから、移行用に残してあるファイルなのでしょう。
以下のコミットで変更を入れています。
Revision: ff1b0277a5b2a0631555d969123fc72c1b8081a9
Message:
modified to import SQLitePCLRaw.lib.e_sqlite3.targets so as to avoid writing code to copy dlls directly.
8. そして e_sqlite3.dll を使わない方法へ
で、e_sqlite3.dll の問題が解決したかと思ったらそうではなく、具体的には ASP.NET 上で EntityFrameworkCore.Sqlite を使おうとするとやはり e_sqlite3.dll がロードできないという問題に遭遇しました。 ASP.NET ではどうも個々の DLL を一時的なファイル置き場にコピーしてから実行しているようで、e_sqlite3.dll を移動できず動的なロードに失敗している様子。
ということで 次の案として以下の変更を実施しました。
- Microsoft.EntityFrameworkCore.Sqlite3 をアンインストール
- Microsoft.EntityFrameworkCore.Sqlite.Core は残します
- 同じく以下のパッケージをアンインストール(SQLitePCLRaw.provider.e_sqlite3 から上(利用側))
- SQLitePCLRaw.bundle_e_sqlite3
- SQLitePCLRaw.lib.e_sqlite3
- SQLitePCLRaw.provider.dynamic_cdecl
- SQLitePCLRaw.bundle_winsqlite3 を導入
Windows のシステムに導入されている SQLite3 実装(sqlite3.dll)を使うための変更です。
今回のサンプルプログラムでは以上の変更で動きました。(以下がコミット)
Revision: ca3127d41929aaf05de221d72dd18c0b68a7a384
Message:
modified to use SQLitePCLRaw.provider.winsqlite3 instead of SQLitePCLRaw.lib.e_sqlite3.
但し ASP.NET のプロジェクトでは以下のコードを挿入する必要がありました。
SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_winsqlite3());
挿入するコードは以下でよいと複数のドキュメントに記載があるのですが、何故かプロジェクト内でメソッドを呼び出せず。 未解決です。
SQLitePCL.Batteries.Init()
詳細
主に以下のページの私の理解のメモになります。
Microsoft.EntityFrameworkCore.Sqlite はいくつかの層により構成されています。
- SQLitePCL
- SQLite Portable Class Library らしい。パッケージ名的には SQLitePCLRaw.Core。 多分複数のバージョンの SQLite を使い分けるための基盤ライブラリ。
- SQLitePCLRaw.provider.e_sqlite3
- SQLitePCL の e_sqlite3.dll 用実装。 e_sqlite3.dll はモジュールの横に置いておき、動的に読み込む様子。 なお SQLitePCLRaw.provider.dynamic_cdecl というのは DLL 版を読む汎用実装で(DLL を切り替え可能にしたもの)、パッケージの依存関係から推察するにe_sqlite3 はこれを使って実装されていると思われる。
- SQLitePCLRaw.provider.winsqlite3
- Windows10 から Windows が SQLite3.dll を抱えているようで、そのバージョンを使う provider 実装。
- SQLitePCLRaw.bundle.(いろいろ)
- provider と SQLitePCLCore をまとめてインストールするためのパッケージ。
- Microsoft.EntityFrameworkCore.Sqlite.Core
- Microsoft.EntityFrameworkCore.Sqlite の本体。
- Microsoft.EntityFrameworkCore.Sqlite
- e_sqlite3 版の provider を使う EntityFrameworkCore 実装。具体的には SQLitePCLRaw.bundle_e_sqlite3 を参照している。
前回 までは以下のパッケージを導入していました。
- Microsoft.EntityFrameworkCore.Sqlite
- Microsoft.EntityFrameworkCore.Tools
- Microsoft.EntityFrameworkCore.Proxies
今回のおすすめは以下のパッケージを導入することになります。
- Microsoft.EntityFrameworkCore.Sqlite.Core (3.1.32)
- SQLitePCLRaw.bundle.winsqlite3 (2.1.2)
- Microsoft.EntityFrameworkCore.Tools (3.1.32)
- Microsoft.EntityFrameworkCore.Proxies (3.1.32)
参考ページ
- そもそも SQLite3 って Windows に標準で含まれているのかな、と思って検索したページ。 Windows SDK に含まれているならよいでしょう
(SQLitePCLRaw に関する参考になりそうなのでメモ。)