Do Entity Framework提供将DB类型转换为C#类型的实用程序
本文关键字:类型 实用程序 类型转换 DB Framework Entity Do | 更新日期: 2023-09-27 18:30:03
我正在使用反射和类型生成器等构建一个动态类,我想知道如何将类型转换为c#类型
目前我是这样做的,但EF提供这种东西吗?
case "uniqueidentifier":
return typeof(Guid);
case "bit":
return typeof(Boolean);
case "nvarchar":
return (typeof(string));
case "datetime":
return typeof(DateTime);
case "float":
return typeof(double);
case "int":
return (typeof(int));
感谢
更新我认为EF到目前为止还没有公开的公用设施。接受的答案与EF无关。那里的图书馆完全不同。
Ryszard Dżegan已经给出了答案,但它不能在TT模板或edmx之外使用(或者可能是我不知道的)
我不知道这样一个公共方法(我认为没有……它可以被接受作为答案)
然而,尝试解压缩sqlmetal.exe,您可以很好地了解默认关联是如何在内部实现的:
在类LinqToSqlShared.Utility.DbTypeSystem(内部类)中,可以找到方法:
internal static Type GetClosestRuntimeType(SqlDbType sqlDbType)
{
switch (sqlDbType)
{
case SqlDbType.BigInt:
return typeof(long);
case SqlDbType.Binary:
case SqlDbType.Image:
case SqlDbType.Timestamp:
case SqlDbType.VarBinary:
return typeof(Binary);
case SqlDbType.Bit:
return typeof(bool);
case SqlDbType.Char:
case SqlDbType.NChar:
case SqlDbType.NText:
case SqlDbType.NVarChar:
case SqlDbType.Text:
case SqlDbType.VarChar:
return typeof(string);
case SqlDbType.DateTime:
case SqlDbType.SmallDateTime:
case SqlDbType.Date:
case SqlDbType.DateTime2:
return typeof(DateTime);
case SqlDbType.Decimal:
case SqlDbType.Money:
case SqlDbType.SmallMoney:
return typeof(decimal);
case SqlDbType.Float:
return typeof(double);
case SqlDbType.Int:
return typeof(int);
case SqlDbType.Real:
return typeof(float);
case SqlDbType.UniqueIdentifier:
return typeof(Guid);
case SqlDbType.SmallInt:
return typeof(short);
case SqlDbType.TinyInt:
return typeof(byte);
case SqlDbType.Xml:
return typeof(XElement);
case SqlDbType.Time:
return typeof(TimeSpan);
case SqlDbType.DateTimeOffset:
return typeof(DateTimeOffset);
}
return typeof(object);
}
编辑:
将此作为参考
同一类中还有一个方法
static SqlDbType Parse(string stype)
,它从sql类型字符串定义中返回枚举SqlDbType。
我可以假设,由于实体框架能够在概念模型和存储模型之间创建映射,因此它具有将每个数据库类型强制转换为相应概念类型的内部能力。
此外,实体框架在T4模板中使用EF.Utility.CS.ttinclude标头中存在的辅助类来生成上下文和实体源文件。
EF.Utility.CS.ttinclude反过来在内部使用System.Data.Metadata.Edm命名空间中的类,特别是PrimitiveTypeKind枚举,它涵盖概念类型并构成数据库类型和CLR类型之间的桥梁。
PrimitiveTypeKind枚举的值可以作为PrimitiveType类中的属性找到,该类还有另一个有趣的属性ClrEquivalentType,它按预期返回System.Type.
PrimitiveType类实例可以通过各种方式获取。在T4模板中,实体框架与具有GetPrimitiveTypes方法的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类复制到代码中即可。然而,实现这一目标也有其他方法。如果使用"代码优先"方法,那么有趣的解决方案是使用EdmxWriter.WriteEdmx方法(DbContext,XmlWriter)在MemoryStream中动态创建edmx文件,然后将该流作为参数放入XmlReader.create方法(stream)中,最后在EdmItemCollection构造函数(IEnumerable)中使用xml读取器作为输入参数。
也有用C#类型替换CLR类型的方法(Nullable<System.Int32>===>int?),但情况不同。。。