2013-09-04 8 views
6

I m budowanie klasy dynamicznej za pomocą konstruktora refleksji i typu i wszystko, chcę wiedzieć, jak zrobić rzut bezpośredni od C# typCzy Entity Framework udostępnia narzędzie, które konwertuje typ danych na typ C?

obecnie tak robię, ale robi tego rodzaju rzeczy dostarczone przez 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)); 

dzięki

UPDATE Zakładam, nie ma narzędzie dostarczane przez EF dotychczas który jest publicznie accessible.the odpowiedź zaakceptowana nie ma nic wspólnego z EF. raczej inna biblioteka tam.

Ryszard Dżegan dał odpowiedź, ale to nie może być stosowany na zewnątrz szablonów TT lub edmx (albo może być ja nie wiem)

+1

Czy można uznać za pomocą 'Dictionary 'zamiast instrukcji switch? –

+0

ys ale chcę użyć jakiegoś wewnętrznego dostawcy z ef, który robi rzecz .. nie chcę tego przełącznika i obudowy ... –

+1

Cóż, nie wiem nic w EF, ale na pewno powiedziałbym, że słownik byłby czystszy niż przełącznik/obudowa. –

Odpowiedz

4

nie wiem taką metodę publiczną (myślę, że nie ma nikogo ... to, że mogą być przyjęte jako odpowiedź)

jednak spróbować uncompile sqlmetal.exe, można mieć dobry pomysł, jak domyślne stowarzyszenia realizowane są wewnętrznie:

w klasie LinqToSqlShared.Utility.DbTypeSystem (klasa wewnętrzna) możesz znaleźć metodę:

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:

  • Zobacz this jako odniesienie

  • Istnieje również metoda static SqlDbType Parse(string stype) w tej samej klasie, która zwraca SqlDbType enum z SQL definicji typu string.

+0

dziękuję za skierowanie mnie do sqlmetal, ale moim celem jest to, że mam łańcuchową reprezentację typu bazy danych z tabeli information_schema jak nvarchar, bit, varchar itd. Ta metoda akceptuje sqldbtype jako argument, którego nie znam .. być czymś w EF, który to ładnie robi, muszę dekompilować, że .. –

+0

Wspomniałem o funkcji, która konwertuje ciąg typu db na SqlDbType enum, jak również. Mogę to załączyć w odpowiedzi, jeśli chcesz :) – Olivier

2

mogę założyć, że od Entity Framework jest zdolny do tworzenia mapowania między model koncepcyjny i składowania modelu, posiada wewnętrzną zdolność do oddania każdy typ bazy danych do odpowiedniego typu koncepcyjne.

Co więcej, Entity Framework wykorzystuje klasy pomocnicze, które istnieją w EF.Utility.CS.ttinclude w swoich szablonach T4 nagłówka do generowania plików źródłowych kontekstu i encji.

EF.Utility.CS.ttinclude z kolei używa klas od System.Data.Metadata.Edm Namespace, w szczególności PrimitiveTypeKind Enumeration, który obejmuje typy pojęciowe i stanowi pomost między typami baz danych a typami CLR.

Wartość PrimitiveTypeKind Enumeration można znaleźć w PrimitiveType Class jako własność i że klasa ma inną ciekawą właściwość o nazwie ClrEquivalentType który zgodnie z oczekiwaniami powraca System.Type.

PrimitiveType Class Wystąpienia można pobierać na różne sposoby. W szablonach T4 struktura Entity działa pod numerem EdmItemCollection Class, która ma GetPrimitiveTypes Method.

W szablonów T4, najprostszym sposobem, aby uzyskać dostęp do EdmItemCollection Class jest wykorzystanie (z EF.Utility.CS.ttinclude) metodę CreateEdmItemCollection MetadataLoader, która przyjmuje jako parametr ścieżkę do edmx pliku.

W pliku tt, można napisać:

<#@ 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#> 
<# 
} 
#> 

Rezultatem będzie:

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 

W zwykły kod C#, można zrobić to samo, jeśli trzeba MetadataLoader. Aby pominąć tę przeszkodę, wystarczy skopiować klasę MetadataLoader do kodu. Istnieją jednak inne sposoby osiągnięcia tego celu. Jeśli pracujesz z podejściem Code First, interesującym rozwiązaniem jest użycie EdmxWriter.WriteEdmx Method (DbContext, XmlWriter) w celu dynamicznego utworzenia pliku edmx w MemoryStream, a następnie przesłanie tego strumienia jako argumentu do XmlReader.Create Method (Stream) i ostatecznie użycie czytnika xml jako parametru wejściowego w EdmItemCollection Constructor (IEnumerable).

Istnieją również sposoby zastąpienia typy CLR przez C# typów (dopuszczające wartość null <System.Int32> ==> int?), Ale to już inna historia ...

+0

pracuję nad podejściem dbfirst –

+0

Jeśli masz plik edmx, twoja praca będzie łatwiejsza niż wtedy :) Jeśli nie, możesz wygenerować go w strumieniu pamięci, tak jak to ci pokazałem. –