EntityFramwork -> お試し
今ひとつピンとこないので
勉強のため、テストプロジェクトを作成。
Visual C#: 15.5.4(2017)
EntityFramework なるものを見つけて
ぜひ挑戦したいと思った。
ただ、慣れない VS 環境であることもあり
なかなかピンとこない。
そこで、参考サイトをそのまま実践してみることにした。
SlideShare:「Entity Framework Coreを使ってみる」 公開用(2017-03-07)
左ペイン [インストール済み]-[Visual C#]-[Windows クラシック デスクトップ] 右ペイン [クラス ライブラリ(.NET Framework)] 名前:KptBoardSystem
場所:任意
ソリューション名:「名前」から自動入力
[ソリューションのディレクトリを作成] にチェック
[新しい Git リポジトリの作成] にチェックなし
[OK]
プロジェクトコンテキストメニューから [NuGet パッケージの管理]
Microsoft.EntityframeworkCore で検索
Microsoft.EntityframeworkCore.Sqlite 2.0.1
Microsoft.EntityframeworkCore.Tools 2.0.1
ソリューションのコンテキストメニューから [追加]-[新しいプロジェクト] 後は前述同様に KptBoardSystemTest プロジェクトを作成。
前述同様に、下記を設定。
Microsoft.EntityframeworkCore 2.0.1
xunit 2.3.1
xunit.runner.visualstudio 2.3.1
Moq 4.8.1
P.12 User
P.13 KptBoardModel
Enable-Migrations
Enable-Migrations is obsolete. Use Add-Migration to start using Migrations.
Add-Migration setp00
To undo this action, use Remove-Migration.
- マイグレーションを可能にする
- マイグレーションを追加する
こんな感じで2ファイルが自動生成された。
KptBoardSystem
┗ Migrations
┣ 20180120074120_setp00.cs
┗ KptBoardModelModelSnapshot.cs
Update-Database
Applying migration '20180120074120_setp00'.
Done.
参考サイト P.15 のように処理がズラズラ並ぶのではなく
とても簡素なリアクションでしたw
参考サイトには「ソリューション直下に「kpt.db」が作成される」とあったけど
実際には、ソリューションの2つ上に作成された。
後述の試行錯誤に見られた、テストとの階層の差分があるということは
コマンドを打つ際に、階層を設定するべきなのではないかと思うけど
現在は手法不明。
そこで、
のパスを下記のように変更したところ、ソリューション直下に作成された。
- var connectionString = new SqliteConnectionStringBuilder { DataSource = "../../../kpt.db" }.ToString();
+ var connectionString = new SqliteConnectionStringBuilder { DataSource = "../kpt.db" }.ToString();
この件には、大きな落とし穴が。。。
詳細は、後述の「試行錯誤」コーナーにて。
コマンドを打つ際に、パッケージ マネージャー コンソールにおいて
「既定のプロジェクト」で何を選択しているかでファイル出力場所が変わる。
“kpt.db” というパスの場合は
プロジェクト直下へ生成されるので
KptBoardSystem を選択していれば、
KptBoardSystemTest を選択していれば、
となる。
この場合、テストではファイルが見つからないエラーになってしまうので
「既定のプロジェクト」は注意。
後述の如く、コマンドと実行でファイルパスの意味合いが変わるので
コマンドで生成された DB ファイルを手動で配置換えをした。
テストと本番で DB を分けることも考え
ソリューション直下ではなく、プロジェクト直下としてみる。
つまり、最終的な配置とファイルパスの指定は下記の通り。
var connectionString = new SqliteConnectionStringBuilder { DataSource = "../../kpt.db" }.ToString();
このようなやり方にすることで
コマンドを打つ度に
ファイルの移動が必要。
P.18
KptBoardSystemTest プロジェクト内「参照」のコンテキストメニュー [参照の追加]
「参照マネージャー」
左ペイン [プロジェクト]-[ソリューション]
中央ペイン [KptBoardSystem] にチェック
[OK]
P.19 KptBoardModelTest
using Xunit;
namespace KptBoardSystem.Test
{
public class KptBoardModelTest
{
[Fact]
public void TestInsertUser()
{
using (var db = new KptBoardModel())
{
var user = new User
{
Name = "User01"
};
db.Add(user);
db.SaveChanges();
}
}
}
}
[テスト]-[実行]-[選択したテスト] で、テストを開始。
私の記述ミスのせいで、
var kptBoard = db.KptBoards.Where(b => b.Problem.Contains("続ける")).First();
こちらが空になってしまった。
その際、下記のエラーが出た。
まだ使い方はよくわからない。
P.34 では、u が括弧書きだったのに
今回は括弧がつかない理由がわからない。
var user02 = db.Users.Where((u) => u.Name == "User02").Include("KptBoards").First();
var kptBoard = db.KptBoards.Where(b => b.Problem.Contains("続ける")).First();
LINQ を勉強すべし。
テスト初回実行時、下記のエラーが出た。
Google 先生に質問したところ、どうやら下記パッケージが不足していることらしい。
テストプロジェクトへインストール。
Install-Package SQLitePCLRaw.bundle_e_sqlite3 -Version 1.1.9
Install-Package SQLitePCLRaw.bundle_sqlcipher -Version 1.1.9
Install-Package SQLitePCL.bundle_green -Version 0.9.3
NuGet パッケージ管理からインストールしても OK だと思う。
stackoverflow:Cannot run SQLite.net PCL in ASP.NET MVC(2017-02-09)
上記エラーが取れてホッとしつつテストを行うと
次は下記エラーが出た。
[2018/01/20 21:48:11 Informational] [xUnit.net 00:00:01.5304014] —- Microsoft.Data.Sqlite.SqliteException : SQLite Error 1: ‘no such table: Users’.
Users テーブルが見つからないってさ。。。
kpt.db の中には、確かに Users テーブルがある。
上で、DB ファイルへのパスを変えたからかもしれないと思い
パスを戻すと、エラーが出ないときもあるけど、確実ではないし
値は書き込まれない。
そもそも DB 接続に失敗しているのかと思って
ファイルパスを存在しないパスにしてみたら
エラー内容が下記の通り変わったので、接続には成功しているみたい。
途方に暮れて、ソリューションディレクトリをあちこち見ていたら
想定外の場所に kpt.db ファイルが!!!
コマンドで作成した kpt.db のファイルパスと
テストコードが参照する kpt.db のファイルパスが
異なることが原因だった。
と言っても、何かがおかしいので
いずれわかる日が来ると信じたい。
ともかく、下記のような検証結果だった。
GrandMother
┣ Mother
┃ ┣ KptBoardSystem
┃ ┃ ┣ KptBoardSystem
┃ ┃ ┣ KptBoardSystemTest
┃ ┃ ┃ ┣ bin
┃ ┃ ┃ ┃ ┣ Debug
┃ ┃ ┃ ┃ ┃ ┗ kpt.db // テスト "kpt.db"
┃ ┃ ┃ ┃ ┣ Release
┃ ┃ ┃ ┃ ┗ kpt.db // テスト "../kpt.db"
┃ ┃ ┃ ┗ kpt.db // コマンド "kpt.db"、テスト "../../kpt.db"
┃ ┃ ┗ kpt.db // コマンド "../kpt.db"、テスト "../../../kpt.db"
┃ ┗ kpt.db // コマンド "../../kpt.db"
┗ kpt.db // コマンド "../../../kpt.db"
つまり
コマンドは、プロジェクトディレクトリがルート。
テスト(実行)は、アセンブリ(.dll)本体のある場所がルート?