Entity Framework は概念モデルとストレージ モデルの間のマッピングを作成できるため、各データベース タイプを対応する概念タイプにキャストする内部機能があると想定できます。
さらに、Entity Framework は、T4 テンプレートの EF.Utility.CS.ttinclude ヘッダーに存在する補助クラスを使用して、コンテキストとエンティティのソース ファイルを生成します。
EF.Utility.CS.ttinclude は、System.Data.Metadata.Edm Namespaceのクラスを内部的に使用します。特に、概念型をカバーし、データベース型と CLR 型の間のブリッジを構成するPrimitiveTypeKind Enumerationを使用します。
PrimitiveTypeKind Enumerationの値はPrimitiveType Classのプロパティとして見つけることができ、そのクラスには、予想どおりSystem.Typeを返すClrEquivalentTypeという別の興味深いプロパティがあります。
PrimitiveType クラスのインスタンスは、さまざまな方法で取得できます。T4 テンプレートでは、Entity FrameworkはGetPrimitiveTypes Methodを持つEdmItemCollection クラスで動作します。
T4 テンプレートでEdmItemCollection クラスにアクセスする最も簡単な方法は、MetadataLoader の (EF.Utility.CS.ttinclude から) CreateEdmItemCollection メソッドを使用することです。このメソッドは、edmx ファイルへのパラメーター パスを受け取ります。
tt ファイルでは、次のように記述できます。
<#@ template hostSpecific="true" #>
<#@ output extension=".txt" #>
<#@ include file="EF.Utility.CS.ttinclude" #><#
var edmxPath = "NorthwindModel.edmx"; // <--- Put the path to your model here.
var loader = new MetadataLoader(this);
var edmItemCollection = loader.CreateEdmItemCollection(edmxPath);
var primitiveTypes = edmItemCollection.GetPrimitiveTypes();
#>
<#
foreach (var primitiveType in primitiveTypes)
{
#>
<#= primitiveType#> ==> <#= primitiveType.ClrEquivalentType#>
<#
}
#>
結果は次のようになります。
Edm.Binary ==> System.Byte[]
Edm.Boolean ==> System.Boolean
Edm.Byte ==> System.Byte
Edm.DateTime ==> System.DateTime
Edm.Decimal ==> System.Decimal
Edm.Double ==> System.Double
Edm.Guid ==> System.Guid
Edm.Single ==> System.Single
Edm.SByte ==> System.SByte
Edm.Int16 ==> System.Int16
Edm.Int32 ==> System.Int32
Edm.Int64 ==> System.Int64
Edm.String ==> System.String
Edm.Time ==> System.TimeSpan
Edm.DateTimeOffset ==> System.DateTimeOffset
Edm.Geometry ==> System.Data.Spatial.DbGeometry
Edm.Geography ==> System.Data.Spatial.DbGeography
Edm.GeometryPoint ==> System.Data.Spatial.DbGeometry
Edm.GeometryLineString ==> System.Data.Spatial.DbGeometry
Edm.GeometryPolygon ==> System.Data.Spatial.DbGeometry
Edm.GeometryMultiPoint ==> System.Data.Spatial.DbGeometry
Edm.GeometryMultiLineString ==> System.Data.Spatial.DbGeometry
Edm.GeometryMultiPolygon ==> System.Data.Spatial.DbGeometry
Edm.GeometryCollection ==> System.Data.Spatial.DbGeometry
Edm.GeographyPoint ==> System.Data.Spatial.DbGeography
Edm.GeographyLineString ==> System.Data.Spatial.DbGeography
Edm.GeographyPolygon ==> System.Data.Spatial.DbGeography
Edm.GeographyMultiPoint ==> System.Data.Spatial.DbGeography
Edm.GeographyMultiLineString ==> System.Data.Spatial.DbGeography
Edm.GeographyMultiPolygon ==> System.Data.Spatial.DbGeography
Edm.GeographyCollection ==> System.Data.Spatial.DbGeography
プレーンな C# コードでは、MetadataLoader があれば同じことができます。この障害を回避するには、MetadataLoader クラスをコードにコピーするだけです。ただし、目標を達成するための他の方法もあります。Code First アプローチを使用する場合、興味深い解決策は、EdmxWriter.WriteEdmx メソッド (DbContext、XmlWriter)を使用して edmx ファイルをMemoryStreamで動的に作成し、そのストリームを引数としてXmlReader.Create メソッド (ストリーム)に入れ、最後に使用することです。 EdmItemCollection コンストラクター (IEnumerable)の入力パラメーターとしての xml リーダー。
CLR 型を C# 型に置き換えるメソッド (Nullable<System.Int32> ==> int?) もありますが、それは別の話です...