I can assume that, since the Entity Framework is capable of creating mappings between the conceptual model and the storage model, it has the internal ability to apply each type of database to the corresponding conceptual type.
In addition, the Entity Framework uses the helper classes that exist in the EF.Utility.CS.ttinclude header in their T4 templates to generate context and entity source files.
EF.Utility.CS.ttinclude, in turn, internally uses classes from System.Data.Metadata.Edm Namespace , in particular PrimitiveTypeKind Enumeration , which encompasses conceptual types and represents a bridge between database types and CLR types.
The value of PrimitiveTypeKind Enumeration can be found as a property in the PrimitiveType Class , and this class has another interesting ClrEquivalentType property, which is expected to return System.Type .
Primitive Class types can be extracted in various ways. In T4 templates, the Entity Framework works with the EdmItemCollection Class , which is the GetPrimitiveTypes Method .
In T4 templates, the easiest way to access the EdmItemCollection Class is to use the MetadataLoader (from EF.Utility.CS.ttinclude) CreateEdmItemCollection method, which takes edmx as the path to the file.
In the tt file you can write:
<#@ 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#> <# } #>
The result will be:
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
In simple C # code, you can do the same if you had MetadataLoader. To omit this obstacle, you can simply copy the MetadataLoader class into your code. However, there are other ways to achieve the goal. If you are working with the Code First approach, an interesting solution is to use the EdmxWriter.WriteEdmx Method (DbContext, XmlWriter) to dynamically create an edmx file in a MemoryStream , then put this stream as an argument in the XmlReader.Create Method (Stream) and finally use xml-reader as an input parameter to the EdmItemCollection Constructor (IEnumerable) .
There are also methods for replacing CLR types with C # types (Nullable <System.Int32> ==> int?), But that's another story ...