Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do Entity Framework Provide Utility that convert DB Type To C# Type?

i m building a dynamic class using reflection and type builder and all , i want to know how can i do direct type casting to c# type

currently this way i m doing , but does this kind of thing provided by 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));

thanks

UPDATE i assume there is no utility provided by EF till now which is publicly accessible.the answer accepted has nothing to do with Ef. rather different library there.

Ryszard Dżegan has given answer but it can not be used outside TT templates or edmx (or may be i didn't know)

like image 475
Vishal Sharma Avatar asked Sep 04 '13 06:09

Vishal Sharma


People also ask

What all services does an Entity Framework provide?

The Entity Framework enables developers to work with data in the form of domain-specific objects and properties, such as customers and customer addresses, without having to concern themselves with the underlying database tables and columns where this data is stored.

How does Entity Framework connect to database?

During installation, the EntityFramework NuGet package checks which database server is available. The NuGet package will then update the configuration file by setting the default database server that Code First uses when creating a connection by convention. If SQL Express is running, it will be used.


2 Answers

I dont know such a public method (I think there is none... it that may be accepted as answer)

However, try to uncompile sqlmetal.exe, you can have a good idea of how default associations are implemented internally:

In class LinqToSqlShared.Utility.DbTypeSystem (internal class) you can find the method:

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);
}

edit:

  • See this as a reference

  • There is also a method static SqlDbType Parse(string stype) in the same class which returns an enum SqlDbType from sql type string definition.

like image 141
Olivier Avatar answered Sep 21 '22 17:09

Olivier


I can assume that since Entity Framework is capable of creating Mappings between Conceptual Model and Storage Model, it has internal ability to cast each database type to corresponding conceptual type.

Moreover, Entity Framework uses auxiliary classes that exist in EF.Utility.CS.ttinclude header in its T4 templates to generate context and entities source files.

EF.Utility.CS.ttinclude in turn internally uses classes from System.Data.Metadata.Edm Namespace, in particular PrimitiveTypeKind Enumeration which covers conceptual types and constitutes bridge between database types and CLR types.

Value of PrimitiveTypeKind Enumeration can be found as property in PrimitiveType Class, and that class has another interesting property called ClrEquivalentType which as expected returns System.Type.

PrimitiveType Class instances can be fetched in various ways. In T4 templates Entity Framework works with EdmItemCollection Class which has GetPrimitiveTypes Method.

In T4 templates, the simplest way to access EdmItemCollection Class is to use MetadataLoader's (from EF.Utility.CS.ttinclude) CreateEdmItemCollection method which takes as parameter path to edmx file.

In tt file, you could 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 plain C# code, you could do same thing if you would have MetadataLoader. To omit this obstacle, you can just copy the MetadataLoader class into your code. However there are also other ways to achieve the goal. If you work with Code First approach, the interesting solution is to use EdmxWriter.WriteEdmx Method (DbContext, XmlWriter) in order to create edmx file dynamicly in MemoryStream and then put that stream as argument into XmlReader.Create Method (Stream) and finally use xml reader as input parameter in EdmItemCollection Constructor (IEnumerable).

There are also methods to replace CLR types by C# types (Nullable<System.Int32> ==> int?) but it is a different story...

like image 23
Ryszard Dżegan Avatar answered Sep 22 '22 17:09

Ryszard Dżegan