我可以假设,由于实体框架能够在概念模型和存储模型之间创建映射,它具有将每个数据库类型转换为相应概念类型的内部能力。
此外,Entity Framework 使用其 T4 模板中的 EF.Utility.CS.ttinclude 标头中存在的辅助类来生成上下文和实体源文件。
EF.Utility.CS.ttinclude 反过来在内部使用System.Data.Metadata.Edm 命名空间中的类,特别是PrimitiveTypeKind 枚举,它涵盖概念类型并构成数据库类型和 CLR 类型之间的桥梁。
PrimitiveTypeKind Enumeration的值可以作为PrimitiveType Class中的属性找到,并且该类还有另一个有趣的属性,称为ClrEquivalentType,它按预期返回System.Type。
PrimitiveType 类实例可以通过多种方式获取。在 T4 模板中,实体框架与具有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)以便在MemoryStream中动态创建 edmx 文件,然后将该流作为参数放入XmlReader.Create 方法(Stream),最后使用xml 阅读器作为EdmItemCollection 构造函数 (IEnumerable)中的输入参数。
还有一些方法可以用 C# 类型 (Nullable<System.Int32> ==> int?) 替换 CLR 类型,但这是另一回事......