プライマリ・コンテンツに移動

Oracle® Data Provider for .NET開発者ガイド ODAC 12.2c リリース1 (12.2.0.1) for Microsoft Windows E88311-03 |
| 目次 | 索引

前 | 次 |

# Code First

Entity Framework Code Firstのモデリング・パスを使用して、開発者はデザイナまたはXMLベースの構成ファイルを直接操作するのではなくソース・コードを使用するアプリケーション・ドメイン・モデルを定義します。ソース・コード内で定義されるクラスがモデルになります。Code Firstモデル・パスは、Entity Framework Database FirstおよびModel Firstの既存のパスのかわりに使用できます。Code Firstでは、モデルを構成するコードに定義されるクラスをPlain Old CLR Object (POCO)と言います。この名前は、これらのクラスがEntity Framework自体には依存せず、それから独立していることに由来します。

Code Firstモデリング・パスはOracleでサポートされているため、.NET開発者はOracle Databaseの利点を活用できます。

関連項目:

Entity Framework Code First用の構成

## .NETタイプからOracleタイプへのマッピング

Code Firstパスを使用するとき、モデルはアプリケーションのクラスおよびプロパティによって定義されます。プロパティ・データ型をOracle Database表のデータ型にマップする必要があります。次の表に、サポートされている.NETタイプからOracleタイプへのデフォルトのマッピングと、Stringプロパティをデフォルト以外のOracleタイプにマップする方法をリストします。

表4-24 .NETデータ型からOracleデータ型へのマッピング

.NETデータ型 | Oracleデータ型 | マッピング・メソッド
--- | --- | ---
`Boolean` | `number(1, 0)` | EDMマッピングを使用 注意: EDMマッピング構成を使用する必要があります。詳細は、ドキュメントでEDMマッピングに関する項を参照してください。
`Byte` | `number(3, 0)` | EDMマッピングを使用 注意: EDMマッピング構成を使用する必要があります。詳細は、ドキュメントでEDMマッピングに関する項を参照してください。
`Byte[]` | `blob` | デフォルト
`Int16` | `number(5, 0)` | デフォルト 注意: 整数型のデフォルトのマッピングは、EDMマッピング構成で指定される可能性があります。詳細は、ドキュメントでEDMマッピングに関する項を参照してください。
`Int32` | `number(10, 0)` | デフォルト 注意: 整数型のデフォルトのマッピングは、EDMマッピング構成で指定される可能性があります。詳細は、ドキュメントでEDMマッピングに関する項を参照してください。
`Int64` | `number(19, 0)` | デフォルト 注意: 整数型のデフォルトのマッピングは、EDMマッピング構成で指定される可能性があります。詳細は、ドキュメントでEDMマッピングに関する項を参照してください。
`Decimal` | `number(18, 2)` | デフォルト
`Single` | `binary_float` | デフォルト
`Double` | `binary_double` | デフォルト
`Guid` | `raw(16)` | デフォルト
`DateTime` | `date` | デフォルト
`DateTimeOffset` | t`imestamp with time zone` | デフォルト
`String` | `nclob` | デフォルト
`String` | `clob` | `IsUnicode()` Fluent APIを使用して、Unicodeをfalseに設定します。
`String` | `nvarchar2` | `HasMaxLength()` Fluent APIまたは`MaxLength`データ注釈を使用して、Max Lengthを`<= 2000`に設定します。
`String` | `varchar2` | `HasMaxLength()` Fluent APIまたは`MaxLength`データ注釈を使用して、Max Lengthを`<= 4000`に設定し、`IsUnicode()` Fluent APIを使用してUnicodeをfalseに設定します。
`String` | `nchar` | HasMaxLength() Fluent APIまたはMaxLength注釈を使用して、Max Lengthを`<= 1000`に設定し、HasColumnType() Fluent APIまたはColumnデータ注釈を使用してColumn Typeを`NCHAR`に設定します。
`String` | `char` | `HasMaxLength()` Fluent APIまたは`MaxLength`注釈を使用して、Max Lengthを`<= 2000` に設定し、`HasColumnType()` Fluent APIまたは`Column`データ注釈を使用してColumn Typeを`CHAR`に設定します
`String` | `Long` | `HasColumnType()` Fluent APIまたは`Column`データ注釈を使用して、Column Typeを`LONG`に設定します。 注意: longデータ型は非推奨となったため、使用しないでください。
String | rowid | `HasColumnType()` Fluent APIまたは`Column`データ注釈を使用して、Column Typeを`ROWID`に設定します。
String | urowid | `HasColumnType()` Fluent APIまたは`Column`データ注釈を使用して、Column Typeを`UROWID`に設定します。

注意:

文字ベースの列、たとえば`CHAR`、`NCHAR`、`VARCHAR2`、`NVARCHAR2`は、文字セマンティクスを使用して作成され、指定した`Max Length`の長さの文字を格納できます。ただし、Oracleデータベースの制限により、これらの列には最大`4000`バイトまでしか格納できません。したがって、データとデータベースのキャラクタ・セットによっては1文字に複数バイト分の容量を必要とする場合があるため、これらの列ではたとえ`Max Length`を`4000`文字に設定しても`4000`文字は格納できない場合があります。文字データが`4000`バイトより長くなる可能性がある場合は、`CLOB`列または`NCLOB`列を使用する方が適切です。

Oracleデータ型の特性に対する影響

前述の表にリストした型のマッピングは、デフォルトで発生するマッピング、つまりEntity Frameworkで規則として知られているマッピングです。`String`型で説明しているように、プロパティに対して生成されるOracleデータ型と、そのデータ型の特性に対して影響を及ぼすことができます。生成されるOracleデータ型に影響を及ぼすEntity Frameworkの方法には、データ注釈とCode First Fluent APIの2つがあります。データ注釈の場合は1つ以上の属性でクラス・プロパティを明示的にマークすることができ、Code First Fluent APIの場合は属性ではなくコードを使用して同じ目標を達成できます。データ注釈とCode First Fluent APIに関する詳細は、MSDNでEntity Frameworkのドキュメントを参照してください。

次の表で、使用可能な機能を説明します。

表4-25 データ注釈とCode First Fluent APIのマッピング

データ注釈 | Fluent API | 用途 | 適用対象
--- | --- | --- | ---
`Key` | `HasKey` | プロパティを主キーとして設定します。 | すべてのスカラー型
`Required` | `IsRequired` | データベース列を`NOT NULL`に設定します。 | すべて
`MaxLength` | `HasMaxLength` | プロパティの最大長を指定します。 | `String`
`NotMapped` | `Ignore` | プロパティがデータベース列にマップされていないことを示します。 | すべて
`ConcurrencyCheck` | `IsConcurrencyToken` | オプティミスティックな同時実行性チェックのために列を使用する必要があることを示します。 注意: LOB列が作成されることになるため、無制限の(最大長の指定がない)文字列プロパティでは使用しないでください。同時実行性チェックでLOB列を使用すると、`「ORA-00932: データ型が一致しません」`エラーになります。 | すべて
`TimeStamp` | `IsRowVersion` | 列を`rowversion`列として作成するよう指示します。 | サポート対象外
`Column` | `HasColumnType` | データベース列に使用するプロバイダ固有のタイプを指定します。 注意: 適切な互換性タイプである必要があります。たとえば、`Date`プロパティは数値列にマップするには適切ではありません。タイプを指定する`Column`データ注釈とともに`TypeName`プロパティを使用します。 | すべて
N/A | `IsUnicode` | 列をN-型、つまり`nvarchar2`または`nclob`として作成するよう指示します。デフォルトはtrueです。 注意: `IsUnicode`に相当するデータ注釈はありません。 | `String`
N/A | `HasPrecision` | 小数点プロパティに使用する精度とスケールを指定します。 注意: `HasPrecision`に相当するデータ注釈はありません。 | `Decimal`

## Code First Migrations

Oracle Data Provider for .NETは、Code First Migrations機能をサポートしています。Code First MigrationsとOracle Databaseの併用は、Package Manager Consoleウィンドウの移行コマンドを通じてサポートされます。これらのコマンドの詳細は、MSDNのCode First Migrationsに関するドキュメントを参照してください。

`http://msdn.microsoft.com/en-us/data/jj591621.aspx`

Code First Migrationsは、移行履歴表という表を使用して移行操作とモデル変更を追跡します。ODP.NETのデフォルトでは、コンテキスト接続文字列で指定されたユーザー・スキーマにこの表が作成されます。この表は__MigrationHistoryという名前です。

この表は、コンテキスト接続文字列で指定されたユーザー以外のユーザー・スキーマに作成することができます。これは、移行履歴表のカスタマイズというプロセスを通じて実行されます。このプロセスについては、MSDNで次のドキュメントを参照してください。

`http://msdn.microsoft.com/en-us/data/dn456841`

注意:

- カスタマイズがサポートされているのは、表のユーザー・スキーマの変更のみです。

- Code Firstの自動移行が機能するのは、`dbo`スキーマのみに限定されています。この制限があるため、コードベースの移行を使用する、つまりAdd-Migrationコマンドによって明示的な移行を追加することをお薦めします。

### サポートしているコード移行ファイルのないCode First Migrations

ODP.NETでCode First Migrationsを使用している場合、データベースを更新する前にサポートされているコード移行ファイルが存在しない場合、移行履歴表がドロップされる可能性があります。開発者は、データベースを更新する前にサポートされているコード移行ファイルが追加されていることを確認してください。

次の手順で、移行履歴表を削除できます。

1. アプリケーションを実行して、データベース・オブジェクトを作成します

2. Package Manager ConsoleでEnable-Migrationsを実行します

3. コードをPOCOに変更します

4. Package Manager ConsoleでUpdate-Databaseを実行します

次の手順で、コード移行ファイルを作成します。

1. アプリケーションを実行して、データベース・オブジェクトを作成します

2. Package Manager ConsoleでEnable-Migrations を実行します

3. コードをPOCOに変更します

4. Package Manager ConsoleでAdd-Migration を実行します。この手順は必要なコード移行ファイルを作成します。

5. Package Manager ConsoleでUpdate-Databaseを実行します

## Code Firstデータベースの初期化

ODP.NETでは、Code Firstデータベースを初期化する次のメソッドがサポートされています。

- `CreateDatabaseIfNotExists` (何も指定しない場合はデフォルト)

- `DropCreateDatabaseAlways`

- `DropCreateDatabaseIfModelChanges`

- `NullDatabaseInitializer`

- `MigrateDatabaseToLatestVersion`

これらのメソッドの詳細はMSDNを参照してください。

OracleとSQL Serverではデータベースの定義方法が異なるため、データベースの初期化操作はモデルのすべてのOracleオブジェクトに対して動作します。Oracleデータベースは作成または削除されず、モデルを構成するオブジェクトがこれらの操作のデータベースとみなされます。

## Oracleデータベース・オブジェクトの作成

クライアント・アプリケーションをサポートするために、ODP.NETは必要なデータベース・オブジェクトを作成して維持します。プロバイダによって作成および維持されるデータベース・オブジェクトは、次のとおりです。

- Table

- 表の列

- 主キー

- 外部キー

- 索引

- 順序

- トリガー

注意:

順序とトリガーは、ID列をサポートするためにOracle Database 11gリリース2以下で作成できます。

クライアント・アプリケーション・オブジェクトに直接関係付けられるオブジェクト、たとえばアプリケーション・クラスを表す表や、クラス・プロパティを表す表列などの場合、使用されるオブジェクト名はクライアントによって指定される名前です。これらのオブジェクト名は、Oracle Databaseのオブジェクト識別子の長さ制限に従う必要があります。たとえば、Oracle Databaseでクラス名の長さが有効なオブジェクト識別子の長さを超えている場合、オブジェクトの作成時に`「ORA-00972: 識別子が長すぎます。」`例外が発生します。

残りのオブジェクトについては、指定した名前の長さがデータベース識別子の長さ制限を超える場合、ODP.NETで名前生成アルゴリズムが使用されます。指定した名前の長さがデータベース制限を超えない場合、名前はそのまま使用されます。どの場合でも、識別子の一部として使われている可能性がある大/小文字と特殊文字を維持するために、オブジェクト名は引用識別子として作成されます。

データベース識別子の長さ制限に適合するようにプロバイダで名前が生成された場合、名前はアンダースコア区切りの次の要素で構成されます。

- 元の名前の部分文字列(最初の文字から)

- 元の名前から計算した数値の接尾辞

次の例では、クライアント・アプリケーションで単純なPOCOを使用した名前生成アルゴリズムの結果を示します。

    public class LongSamplePocoTestClassName
    {
      [Key]
      public int Id { get; set; }

      [MaxLength(64)]
      public string Name { get; set; }
    }

生成される表の主キーのデフォルト名は、次のとおりです。

    PK_LongSamplePocoTestClassNames

この名前には31文字含まれている(1バイトを1文字とする)ので、データベース識別子の制限を超えています。書きなおした主キー名は、次のような値になります。

    PK_LongSamplePocoTes_730795129

アルゴリズムは、新しい名前が識別子の長さ制限を超えないようにしつつ、元の名前からできるだけ多くの文字を利用するように設計されています。

表名と所有者の制御

データ注釈とEntity Framework Fluent APIを使用することで、表名と表の所有者を制御することができます。たとえば、規則の命名規則に適合するように表名を明示的に設定することも、あるいは必要な場合にはEntity Frameworkで指定される名前を使用することもできます。`Table`データ注釈を使用して、表名と所有者の両方を制御します。Fluent APIを使用する場合は、`ToTable`メソッドを使用して、`DbContext`から導出されるクラスの`OnModelCreating`オーバーライド内の表名と所有者を制御します。

次の例では、これらの操作を示すために不完全なクラス定義を使用しています。

データ注釈を使用して表名を設定:

    [Table("Employee")]
    public class Employee

Fluent APIを使用して表名を設定:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
      modelBuilder.Entity<Employee>().ToTable("Employee");
    }

データ注釈を使用して表名と所有者を設定:

    [Table("Employee ", Schema="TESTUSER")]
    public class Employee

Fluent APIを使用して表名と所有者を設定:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
      modelBuilder.Entity<Employee>().ToTable("Employee", "TESTUSER");
    }

注意:

上の例のようにデータ注釈またはFluent APIを使用して所有者を設定する場合、名前も設定する必要があります。

デフォルトの表所有者の設定

ユーザー表ごとに表の所有者を設定するかわりに、Entity Framework 6以上では使用するデフォルト所有者を設定することができます。そのためには、`DbContext`から導出されるクラスの`OnModelCreating`オーバーライド内で`HasDefaultSchema`メソッドを呼び出します。

たとえば次のコードでは、デフォルトで`TESTUSER`スキーマ内にすべてのユーザー表が作成されます。

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
      modelBuilder.HasDefaultSchema("TESTUSER");
    }

注意:

所有者名は、大/小文字が区別されます。

関連項目:

Oracle Database管理者ガイド

## デフォルト接続ファクトリの使い方

デフォルト接続ファクトリでは、Oracle接続文字列を`DbContext`コンストラクタに渡すことでODP.NET接続を確立できます。たとえば、ODP.NET管理対象ドライバのデフォルト接続ファクトリを構成するために次のエントリを使用できます。

    <defaultConnectionFactory type="Oracle.ManagedDataAccess.EntityFramework.OracleConnectionFactory,
    Oracle.ManagedDataAccess.EntityFramework,
    Version=6.121.2.0,
    Culture=neutral,
    PublicKeyToken=89b483f429c47342" />

デフォルト接続ファクトリを使用するときに、アプリケーションはOracle接続文字列を次のように`DbContext`ベース・コンストラクタに提供します。

    public class TestContext : DbContext
    {
      public TestContext()
        : base("<connection string>")
      {
      }
    }

ここで、`<connection string>`はODP.NET接続文字列です。これにより、アプリケーションは次のようなコードを使用してデータベースに接続できます。

    using (var ctx = new TestContext())
    {
      ...
    }

その他の情報については、`IDbConnectionFactory`インタフェースのMSDNドキュメントを参照してください。

`http://msdn.microsoft.com/en-us/library/system.data.entity.infrastructure.idbconnectionfactory%28v=vs.113%29.aspx`