スキャフォールディングまたはリバース・エンジニアリング

ODP.NET EF Coreでは、次の表およびビューのスキャフォールディングがサポートされています。

  • リレーショナル表およびリレーショナル・ビュー

  • マテリアライズド・ビュー

通常、ODP.NET EF Coreでは、Oracle Databaseのデータ型とその特性に基づいて適切な.NETデータ型がマップされます。

スキャフォールド時に、開発者はOracle Databaseと.NET間のデフォルトのデータ型マッピングの変更が必要になることがあります。生成されたエンティティのプロパティの.NET CLRタイプを変更する場合は、モデル内の自動生成されたHasColumnType() Fluent APIを削除します。たとえば、Oracle NUMBER(4)は、デフォルトで.NET Byteデータ型にスキャフォールドされます。.NET CLRデータ型を.NET ShortまたはInt16データ型に変更すると、HasColumnType("NUMBER(4)")が削除されるまで、実行時に無効なキャスト例外が発生する可能性があります。

データ型マッピング

この表は、デフォルト・マッピングを示しています。

表5-2 ODP.NET Entity Framework Coreリバース・エンジニアリング・データ型のデフォルト・マッピング

Oracle Databaseデータ型 .NETタイプの別名 .NETデータ型

NUMBER(1)

bool

System.Boolean

NUMBER(2)からNUMBER(4)

byte

System.Byte

NUMBER(5)

short/int16

System.Int16

NUMBER(6)からNUMBER(10)

int/int32

System.Int32

NUMBER(11)からNUMBER(19)

long/int64

System.Int64

NUMBER(>19)

decimal

System.Decimal

NUMBER(p,s)

decimal

System.Decimal

NUMBER

decimal

System.Decimal

BINARY_FLOAT

float

System.Float

BINARY_DOUBLE

double

System.Double

BOOLEAN

bool

System.Boolean

TIMESTAMP

DateTime

System.DateTime

TIMESTAMP WITH TIMEZONE

DateTimeOffset

System.DateTimeOffset

TIMESTAMP WITH LOCAL TIMEZONE

DateTime

System.DateTime

DATE

DateTime

System.DateTime

INTERVALDAYTOSECOND

TimeSpan

System.Timespan

INTERVALYEARTOMONTH

string

System.String

VARCHAR2

string

System.String

JSON

string

System.String

NVARCHAR2

string

System.String

CHAR

string

System.String

NCHAR

string

System.String

CLOB

string

System.String

NCLOB

string

System.String

RAW

byte[]

System.Byte[]

BLOB

byte[]

System.Byte[]

XMLTYPE

string

System.String

ROWID

string

System.String

UROWID

string

System.String

LONG

string

System.String

BFILE

byte[]

System.Byte[]

LONG RAW

byte[]

System.Byte[]

VECTOR

string

System.String

別のスキーマからの表のスキャフォールディング

開発者は、接続先のユーザー/スキーマ以外のスキーマから表をスキャフォールドできます。接続先のユーザーには、他のスキーマのオブジェクトにアクセスする権限が必要です。これらの権限が付与されると、開発者はEntity Framework Coreのパッケージ・マネージャ・コンソール(PMC)ツールを使用してスキャフォールディング操作を実行できます。たとえば:

Scaffold-DbContext "User Id=scott;Password=<password>;Data Source=myhost:1521/mydb;" 
Oracle.EntityFrameworkCore -Schemas HR -Tables EMPLOYEES

開発者は、–Schemasおよび–Tablesパラメータを使用して、Entity Framework Coreモデルについてスキャフォールドするスキーマおよび表/ビューを指定できます。あるユーザー/スキーマに接続して2つ目のスキーマから表を作成する場合、そのユーザーには、その2つ目のスキーマに対するSELECT以上の権限が必要です。

次の表に、Package Manager ConsoleコマンドScaffold-DbContextを使用した既存のモデルのスキャフォールド中に、–Schemasまたは–Tablesパラメータ(あるいはその両方)を指定するか、デフォルトのままにした場合のODP.NET Entity Framework Coreの動作を示します。次のすべてのサンプル・コマンドの抜粋では、Scaffold-DbContext構文を使用します。EF Coreツール・コマンドdotnet ef dbcontext scaffoldを使用すると、同様の機能が使用できます。

表5-3 スキーマ・フィルタと表フィルタのマッピング

スキーマ・フィルタと表フィルタのマッピング スキーマ・フィルタなし スキーマ・フィルタ

表フィルタなし

現在のユーザー/スキーマ内のすべての表/ビューを生成します

ボックス1

指定されたユーザー/スキーマ内のすべての表/ビューを生成します

ボックス2

表フィルタ

現在のユーザー/スキーマ内の指定された表/ビューを生成します

ボックス3

現在のスキーマ内の指定された表/ビューおよび指定されたユーザー/スキーマ内のすべての表/ビューを生成します

フィルタされた結果には、ボックス2ボックス3の結果の組合せが含まれます。

他のスキーマの表/ビューをスキャフォールドするには、スキーマ名を前に付加して-Tables <schema>.<table/view>とします。

たとえば、次のスニペットは3つの異なるスキーマの3つの表をスキャフォールドします。

-Tables SCHEMA1.TABLEA, SCHEMA2.TABLEB, SCHEMA3.TABLEC

スキーマ名または表名にピリオドなどの特殊文字が含まれている場合は、–Tablesオプションを使用するときに、大カッコを使用してスキーマ名および表名を区切ります。

-Tables [SCHEMA1].[TABLEA]

ビューのスキャフォールディング

データベースのリレーショナル・ビューとマテリアライズド・ビューのスキャフォールディングのみがサポートされています。これらのビューは、読取り専用または更新可能にすることができます。-Tablesパラメータを使用して、スキャフォールドするビューを指定します。パラメータを空白(デフォルト)のままにすると、すべてのユーザー表、リレーショナル・ビューおよびマテリアライズド・ビューがスキャフォールドされます。

データ型マッピングのカスタマイズ

デフォルトのデータ型マッピングが.NETアプリケーションに最適でない場合は、スキャフォールドされたデータ型マッピングを変更できます。たとえば、NUMBER(1)は、デフォルトでは.NET boolにマップされます。その列データにブール値以外の数値が含まれている場合は、.NET byteへのマッピングのほうが適切です。

マッピングをカスタマイズするには、Oracle EF Coreアプリケーションでリバース・エンジニアリング・テンプレートまたはT4テキスト・テンプレートを使用する必要があります。これらのテンプレートでは、代替マッピング(スキャフォールディング中にOracle EF Coreによって使用できる)が提供されます。次の表に、共通の一連の代替データ型マッピングを示します。これらは、スキャフォールディングの場合は、Oracleデータベース型と.NET型の間の、より補完的な一致です。

表5-4 ODP.NET Entity Framework Coreのスキャフォールディングのデフォルト・データ型と代替データ型のマッピング

Oracle Databaseデータ型 デフォルトの.NET型の別名 より補完的な.NET型の別名

NUMBER(1)

bool

byte

NUMBER(2)からNUMBER(4)

byte

Int16

NUMBER(5)

Int16

Int32

NUMBER(6)からNUMBER(10)

Int32

Int64

NUMBER(10)からNUMBER(19)

Int64

Decimal

より補完的な.NETデータ型の利点の1つは、マップされたOracle Databaseデータ型の考えられる値すべてをそれらに格納できることです。

データ型マッピングのカスタマイズのためのT4テンプレートの使用

標準の.NET T4テンプレートでは、EF Coreのスキャフォールディングのための、データ型マッピングのカスタマイズの情報が提供されます。テンプレートを使用するには、次のステップを実行します。

  1. EF Coreテンプレートのパッケージをインストールします。たとえば、次の.NET CLIコマンドを使用してそのパッケージを組み込むことができます:

    dotnet new install Microsoft.EntityFrameworkCore.Templates
  2. Oracle EF Coreのデフォルト・テンプレートをプロジェクトに追加します。これも、次に示すように.NET CLIで実行できます:

    dotnet new ef-templates

    これで、2つのファイルDbContext.t4およびEntityType.t4を含む新しいプロジェクト・ディレクトリCode-Templates/EFCoreが表示されるようになります。DbContext.t4テンプレートは、データベースのDbContextクラスをスキャフォールドするために使用されます。EntityType.t4テンプレートは、データベース内の表ごとやビューごとにエンティティ型クラスをスキャフォールドするために使用されます。次のステップでは、EntityType.t4テンプレートを使用します。

  3. EntityType.t4テンプレートを使用すると、任意のCLR型を特定のOracleデータベース型にマップできます。このテンプレート・スニペットでは、NUMBER(1)の列Col1を、デフォルトの.NET bool型ではなく.NET shortデータ型にマップしています。

            //Specify the store type custom mapping to your chosen the CLR type
            var clrType = (property.Name == "Col1" && property.GetColumnType() == "NUMBER(1)")
                ? typeof(short)
                : property.ClrType;
     
            //Add any required ‘usings’ for the clrType
            usings.AddRange(code.GetRequiredUsings(clrType));
     
            var needsNullable = Options.UseNullableReferenceTypes && property.IsNullable && !clrType.IsValueType;
            var needsInitializer = Options.UseNullableReferenceTypes && !property.IsNullable && !clrType.IsValueType;
    #>
        public <#= code.Reference(clrType) #><#= needsNullable ? "?" : "" #> <#= property.Name #> { get; set; }<#= needsInitializer ? " = null!;" : "" #>
    <#
            firstProperty = false;
    
    

    新しく追加されたテンプレートにより、Oracle EF Coreのデフォルト型マッピングがオーバーライドされます。

    Oracleは、Oracle .NET GitHubサンプル・コード・サイトで、開発者がそのまま使用することやカスタマイズすることができるサンプルT4テキスト・テンプレートを提供しています。スニペットを、最小限のカスタマイズで、アプリケーションのT4テキスト・テンプレートに直接コピーできます。

    テンプレート内のプロパティ名は、標準プロパティ・ネーミング・スキームに従ってスキャフォールディングによって生成されたものです。前述の例では、データベース列COLl1が、.NETプロパティ名Col1になります。次の例では、データベース列C01_SMALLINTが、プロパティ名C01SmallIntになります。

    var clrType = (property.Name == "C01SmallInt" && property.GetColumnType() == "NUMBER(38)")
                ? typeof(short)
                : property.ClrType;
    
    

    .NET型名を決定する簡単な方法は、テンプレートなしでスキャフォールディングを実行することです。

    CLR型など、プロパティのなんらかの側面を変更する場合は、property.clrTypeではなく、この例のclrType参照で示しているように、そのプロパティの出力時に、適切な変更された変数が使用されていることを確認してください。

    public <#= code.Reference(clrType) #><#= needsNullable ? "?" : "" #> <#= 
    property.Name #> { get; set; }<#= needsInitializer ? " = null!;" : "" #>