Entity Framework - Code First Migration - Oracle ではまって勉強中...

# はじめに
久々にはまったので、ここに記載を追記!!

# TODO
- [ ] 

# ノウハウ

## はまり④：自動採番動かない...

◆【Oracle】シーケンス（sequence）を使って自動発番する
　https://notepad-blog.com/content/147/
　　※ここと同じSequence/Triggerの自動採番方式で動かなくなる...
◆連番の自動採番方法
　https://ameblo.jp/archive-redo-blog/entry-10035189031.html
◆Entity Framework + Oracle で自動採番できるのか調べた
　https://minato128.hateblo.jp/entry/2013/03/06/001756


## はまり③：エンティティの検証に失敗

◆EntityFramework SaveChange()時の例外発生時にSQLのエラーを表示させる
　https://qiita.com/yahweh/items/1f1f1bf8b09c7d60cfbd

◆[EntityFramework]SaveChanges() 時の検証
　http://itkaeru.blogspot.com/2013/03/entityframeworksavechanges.html

◆DbEntityValidationException-エラーの原因を簡単に特定するにはどうすればよいですか？
　https://www.javaer101.com/en/article/8669807.html

◆DbEntityValidationException - エラーの原因を簡単に判断する方法
　https://www.it-mure.jp.net/ja/c%23/dbentityvalidationexception-%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AE%E5%8E%9F%E5%9B%A0%E3%82%92%E7%B0%A1%E5%8D%98%E3%81%AB%E5%88%A4%E6%96%AD%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/1072571349/


## はまり②：複合キー追加
全テーブルに[Key]を追加したら大量のエラーが発生して困った...

### 参考サイト

◆リレーションシップ属性: InverseProperty と ForeignKey
　https://docs.microsoft.com/ja-jp/ef/ef6/modeling/code-first/data-annotations
◆リレーションシップ、ナビゲーション プロパティ、および外部キー
　https://docs.microsoft.com/ja-jp/ef/ef6/fundamentals/relationships


◆新しいデータベースの Code First
　https://docs.microsoft.com/ja-jp/ef/ef6/modeling/code-first/workflows/new-database
　　※EF でサポートされている注釈の完全な一覧は次のとおりです。
　　　KeyAttribute
　　　Stringlength 属性
　　　MaxLengthAttribute
　　　ConcurrencyCheckAttribute
　　　RequiredAttribute
　　　タイムスタンプ属性
　　　ComplexTypeAttribute
　　　ColumnAttribute
　　　TableAttribute
　　　InversePropertyAttribute
　　　ForeignKeyAttribute
　　　DatabaseGeneratedAttribute
　　　NotMappedAttribute

◆Entity Framework 1対1
　https://memo-c-sharp.blogspot.com/2017/02/entity-framework-11.html
◆エンティティフレームワークの1対1の関係で、連合の主な終わりは何を意味しますか？c＃、エンティティフレームワーク、データベース設計、外部キー関係
　https://living-sun.com/ja/c/148523-what-does-principal-end-of-an-association-means-in-11-relationship-in-entity-framework-c-entity-framework-database-design-foreign-key-relationship.html
　　※1対1では[Required]を付与する必要がある!!

◆EntityFramework Core 3.1 を使って、色々な一対多のリレーションを試してみた
　https://thinkami.hatenablog.com/entry/2019/12/18/230557
　　※InversePropertyって何だ!?って時に
　　※後でデータアノテーションは後で一通りチェックしないと...

◆c# - 2つのエンティティ間の複数の関係を定義する方法は？
　https://cloud6.net/so/c%23/1718918
　　※下記エラーメッセージの対応パターン
　　　「System.InvalidOperationException: 'タイプ' User 'のナビゲーションプロパティ' Photo.Owner 'で表される関係を特定できません。関係を手動で構成するか、「[NotMapped]」属性を使用するか、「OnModelCreating」の「EntityTypeBuilder.Ignore」を使用して、このプロパティを無視します。」

◆Entity Framework Core におけるリレーションシップについて
　http://kuttsun.blogspot.com/2018/01/entity-framework-core_11.html
◆Shadow および Indexer プロパティ
　https://docs.microsoft.com/ja-jp/ef/core/modeling/shadow-properties
　　★この
　





## はまり①：外部キー制約の有効/無効化
Oracleはキー名称が30(!?)を超えると数字の文字列に置換される（⇒FK_WakaOnsiteCourse_1391782694）
これをMigrationしようとすると、環境によってはキー名が異なることが原因で自動生成された操作が失敗してしまう。そのため、外部キー情報を取得してそれに対して操作することで問題の回避を図る。

```sql:DisableDey.sql
BEGIN
  FOR row IN (SELECT B.TABLE_NAME, B.CONSTRAINT_NAME
               FROM DBA_CONSTRAINTS A,DBA_CONSTRAINTS B
               WHERE A.CONSTRAINT_NAME = B.R_CONSTRAINT_NAME
                 AND A.CONSTRAINT_TYPE = 'P'
                 AND B.CONSTRAINT_TYPE = 'R'
                 AND A.TABLE_NAME = 'TableName'
                 AND B.OWNER = 'SchemaName')
  LOOP
    EXECUTE IMMEDIATE 'ALTER TABLE ' || '""SchemaName"".""' || row.TABLE_NAME || '""' ||
                      ' DISABLE CONSTRAINT ""' || row.CONSTRAINT_NAME || '""';
  END LOOP;
END;
```

```csharp:202200000000000_Migration.cs
        {
            SqlFile(@"Migrations\DisableKey.sql");
        }
```

```csharp:Configuration.cs
        protected override void Seed(OracleDBContext context)
        {
            context.Database.ExecuteSqlCommand(AlterForeignKeyStatus("Departments"));
        }

        private String AlterForeignKeyStatus(String tableName)
        {
            var sqlCommand = new StringBuilder();
            sqlCommand.AppendLine(@"BEGIN");
            sqlCommand.AppendLine(@"  FOR row IN (SELECT B.TABLE_NAME, B.CONSTRAINT_NAME");
            sqlCommand.AppendLine(@"               FROM DBA_CONSTRAINTS A,DBA_CONSTRAINTS B");
            sqlCommand.AppendLine(@"               WHERE A.CONSTRAINT_NAME = B.R_CONSTRAINT_NAME");
            sqlCommand.AppendLine(@"                 AND A.CONSTRAINT_TYPE = 'P'");
            sqlCommand.AppendLine(@"                 AND B.CONSTRAINT_TYPE = 'R'");
            sqlCommand.AppendLine(@"                 AND A.TABLE_NAME = '" + tableName + @"'");
            sqlCommand.AppendLine(@"                 AND B.OWNER = 'SchemaName')");
            sqlCommand.AppendLine(@"  LOOP");
            sqlCommand.AppendLine(@"    EXECUTE IMMEDIATE 'ALTER TABLE ' || '""SchemaName"".""' || row.TABLE_NAME || '""' ||");
            sqlCommand.AppendLine(@"                      ' ENABLE CONSTRAINT ""' || row.CONSTRAINT_NAME || '""';");
            sqlCommand.AppendLine(@"  END LOOP;");
            sqlCommand.AppendLine(@"END;");
            return sqlCommand.ToString();
        }
```

```sql:tool.sql
-- PrimaryKey情報取得
SELECT A.CONSTRAINT_NAME, A.STATUS
  FROM DBA_CONSTRAINTS A
  WHERE A.CONSTRAINT_TYPE = 'P'
    AND A.TABLE_NAME = 'TableName'
    AND A.OWNER = 'SchemaName'
;

-- ForeignKey制約情報取得
-- SELECT B.OWNER || '/' || B.TABLE_NAME || '/' || B.CONSTRAINT_NAME || '/' || B.STATUS
SELECT B.CONSTRAINT_NAME, B.STATUS
  FROM DBA_CONSTRAINTS A,DBA_CONSTRAINTS B
  WHERE A.CONSTRAINT_NAME = B.R_CONSTRAINT_NAME
    AND A.CONSTRAINT_TYPE = 'P'
    AND B.CONSTRAINT_TYPE = 'R'
    AND A.TABLE_NAME = 'TableName'
    AND B.OWNER = 'SchemaName'
;

-- 結果表示(デバッグ用)
SET SERVEROUTPUT ON

-- 外部キー無効化
alter table "SchemaName"."WakaOnsiteCourses" disable constraint "FK_WakaOnsiteCourse_1391782694";
alter table "SchemaName"."OnlineCourses" disable constraint "FK_OnlineCourses_DepartmentID";
-- 外部キー有効化
alter table "SchemaName"."WakaOnsiteCourses" enable constraint "FK_WakaOnsiteCourse_1391782694";
alter table "SchemaName"."OnlineCourses" enable constraint "FK_OnlineCourses_DepartmentID";

```


# 参考サイト

:link: [門外不出のOracle現場ワザ　第１章　目からウロコのOracleパフォーマンス分析テクニック](https://www.oracle.com/technetwork/jp/articles/chapter1-2-084070-ja.html "門外不出のOracle現場ワザ　第１章　目からウロコのOracleパフォーマンス分析テクニック")

:link: [c＃ – EFによって生成されたクエリは実行に時間がかかりすぎる](https://codeday.me/jp/qa/20190214/249264.html "c＃ – EFによって生成されたクエリは実行に時間がかかりすぎる")

:link: [C# Entity Framework 6 の DbContext で変更されたレコードと変更前後の値を取得する](https://mseeeen.msen.jp/db-context-change-tracker-in-entity-framework-6/ "C# Entity Framework 6 の DbContext で変更されたレコードと変更前後の値を取得する")
　※変更追跡の情報を取得する ChangeTracker の Entries メソッド

:link: [[C#]LINQ to Entitiesで発行されているSQL文を見たい](http://blogs.wankuma.com/kazuki/archive/2009/06/01/173926.aspx "[C#]LINQ to Entitiesで発行されているSQL文を見たい")
　※ToTraceStringメソッド

:link: [EntityFramework(18):トランザクション処理](http://gushwell.ldblog.jp/archives/52440184.html "EntityFramework(18):トランザクション処理")

:link: [4. データの挿入、読み出し、更新、削除](https://densan-labs.net/tech/codefirst/adddelete.html "4. データの挿入、読み出し、更新、削除")
　
:link: [Code First Migrationでぐだぐだになる](https://nasu38yen.wordpress.com/2014/01/22/code-first-migrationでぐだぐだになる/ "Code First Migrationでぐだぐだになる")