Niestety, o ile wiem, to mapowanie nie jest ujawnione w kodzie wewnątrz .NET Framework. Przeglądałem wcześniej źródło referencyjne .NET Framework i odkryłem, że w kodzie .NET jest dużo długich instrukcji przełączania na różne typy, tak jak te, których próbujesz uniknąć, ale żaden z nich nie wygląda być odsłoniętym na zewnątrz.
Jeśli naprawdę chcesz tylko mapować z SqlTypes do najbardziej podobnego typu .NET, myślę, że najlepiej jest po prostu zamienić tabelę mapowania in the MSDN docs na kod. Zauważ, że tabela w MSDN ma (przynajmniej) dwa błędy: # 1: nie ma typu .NET o nazwie "DateTime2" (użyłem DateTime) i nie ma również typu o nazwie "Xml" (użyłem SqlXml).
W każdym razie, oto mapowanie, którego używałem - używanie Słownika zamiast przełącznika dla łatwego dostępu bez oddzielnej metody.
public static Dictionary<SqlDbType, Type> TypeMap = new Dictionary<SqlDbType, Type>
{
{ SqlDbType.BigInt, typeof(Int64) },
{ SqlDbType.Binary, typeof(Byte[]) },
{ SqlDbType.Bit, typeof(Boolean) },
{ SqlDbType.Char, typeof(String) },
{ SqlDbType.Date, typeof(DateTime) },
{ SqlDbType.DateTime, typeof(DateTime) },
{ SqlDbType.DateTime2, typeof(DateTime) },
{ SqlDbType.DateTimeOffset, typeof(DateTimeOffset) },
{ SqlDbType.Decimal, typeof(Decimal) },
{ SqlDbType.Float, typeof(Double) },
{ SqlDbType.Int, typeof(Int32) },
{ SqlDbType.Money, typeof(Decimal) },
{ SqlDbType.NChar, typeof(String) },
{ SqlDbType.NText, typeof(String) },
{ SqlDbType.NVarChar, typeof(String) },
{ SqlDbType.Real, typeof(Single) },
{ SqlDbType.SmallInt, typeof(Int16) },
{ SqlDbType.SmallMoney, typeof(Decimal) },
{ SqlDbType.Structured, typeof(Object) }, // might not be best mapping...
{ SqlDbType.Text, typeof(String) },
{ SqlDbType.Time, typeof(TimeSpan) },
{ SqlDbType.Timestamp, typeof(Byte[]) },
{ SqlDbType.TinyInt, typeof(Byte) },
{ SqlDbType.Udt, typeof(Object) }, // might not be best mapping...
{ SqlDbType.UniqueIdentifier, typeof(Guid) },
{ SqlDbType.VarBinary, typeof(Byte[]) },
{ SqlDbType.VarChar, typeof(String) },
{ SqlDbType.Variant, typeof(Object) },
{ SqlDbType.Xml, typeof(SqlXml) },
};
Należy pamiętać, że jedna rzecz, trzeba zwrócić uwagę na to rozmiar/precision-- niektóre typy SQL (np varchar
) mają limity rozmiaru, natomiast typy .NET (np string
) nie. Zatem znajomość najbardziej prawdopodobnego typu .NET nie jest wystarczająca ... jeśli używasz tego na przykład do sprawdzania reguł sprawdzania poprawności, musisz także mieć możliwość uniemożliwienia użytkownikom wprowadzania nieprawidłowych wartości (np. Zbyt dużych), wiedząc więcej o parametrze, np. precyzji. Zwróć uwagę, że jeśli zajrzysz do źródła SqlClient, używają specjalnego kodu do obsługi przypadków, takich jak ustawienie precyzji typu dziesiętnego z odpowiedniej precyzji SQL.
Należy pamiętać, że jeśli jedynym powodem, dla którego potrzebujesz typu .NET, jest możliwość dodania danych do zapisanego parametru proc, możesz spróbować użyć ToString() dla wszystkich wartości .NET, wstawiając ciąg znaków do właściwość Value parametru SqlParameter i zobacz, czy framework wykona dla Ciebie konwersję/parsowanie. Na przykład dla parametru XML lub Date możesz odejść z wysyłaniem łańcucha znaków.
Ponadto, zamiast używać refleksji do znalezienia metody Parse() dla każdego typu, ponieważ istnieje znana (i mała) lista typów, można uzyskać lepszą wydajność za pomocą silnie wpisanego kodu parsowania dla każdego, np. kod poniżej. (Zwróć uwagę, że kilka typów (na przykład SqlDbType.UDT) nie muszą mieć oczywisty parser method-- będziesz musiał dowiedzieć się, w jaki sposób chcesz obsłużyć tych.)
public static Dictionary<SqlDbType, Func<string, object>> TypeMapper = new Dictionary<SqlDbType, Func<string, object>>
{
{ SqlDbType.BigInt, s => Int64.Parse(s)},
{ SqlDbType.Binary, s => null }, // TODO: what parser?
{ SqlDbType.Bit, s => Boolean.Parse(s) },
{ SqlDbType.Char, s => s },
{ SqlDbType.Date, s => DateTime.Parse(s) },
{ SqlDbType.DateTime, s => DateTime.Parse(s) },
{ SqlDbType.DateTime2, s => DateTime.Parse(s) },
{ SqlDbType.DateTimeOffset, s => DateTimeOffset.Parse(s) },
{ SqlDbType.Decimal, s => Decimal.Parse(s) },
{ SqlDbType.Float, s => Double.Parse(s) },
{ SqlDbType.Int, s => Int32.Parse(s) },
{ SqlDbType.Money, s => Decimal.Parse(s) },
{ SqlDbType.NChar, s => s },
{ SqlDbType.NText, s => s },
{ SqlDbType.NVarChar, s => s },
{ SqlDbType.Real, s => Single.Parse(s) },
{ SqlDbType.SmallInt, s => Int16.Parse(s) },
{ SqlDbType.SmallMoney, s => Decimal.Parse(s) },
{ SqlDbType.Structured, s => null }, // TODO: what parser?
{ SqlDbType.Text, s => s },
{ SqlDbType.Time, s => TimeSpan.Parse(s) },
{ SqlDbType.Timestamp, s => null }, // TODO: what parser?
{ SqlDbType.TinyInt, s => Byte.Parse(s) },
{ SqlDbType.Udt, s => null }, // consider exception instead
{ SqlDbType.UniqueIdentifier, s => new Guid(s) },
{ SqlDbType.VarBinary, s => null }, // TODO: what parser?
{ SqlDbType.VarChar, s => s },
{ SqlDbType.Variant, s => null }, // TODO: what parser?
{ SqlDbType.Xml, s => s },
};
kod używany powyżej jest całkiem proste, na przykład :
string valueToSet = "1234";
SqlParameter p = new SqlParameter();
p.SqlDbType = System.Data.SqlDbType.Int;
p.Value = TypeMapper[p.SqlDbType](valueToSet);
Co dokładnie próbujesz zrobić? Czy mam rację, gdy czytam, że masz kolekcję SqlParameters i masz kolekcję wartości .net? A chcesz "przekonwertować" swoją kolekcję wartości na właściwości SqlParameter.Value? Przykład: SqlParamaters [0].Wartość = MagicConvert (Wartości [0]); – Zenuka