2016-03-02 8 views
8

मैं .NET System.Type और SqlDbType के बीच एक स्मार्ट रूपांतरण की तलाश में था। क्या मैंने पाया यह निम्नलिखित विचार था:.NET सिस्टम प्रकार SqlDbType

private static SqlDbType TypeToSqlDbType(Type t) 
{ 
    String name = t.Name; 
    SqlDbType val = SqlDbType.VarChar; // default value 
    try 
    { 
     if (name.Contains("16") || name.Contains("32") || name.Contains("64")) 
      { 
       name = name.Substring(0, name.Length - 2); 
      } 
      val = (SqlDbType)Enum.Parse(typeof(SqlDbType), name, true); 
     } 
     catch (Exception) 
     { 
      // add error handling to suit your taste 
     } 

     return val; 
    } 

ऊपर कोड वास्तव में अच्छा नहीं है और एक कोड गंध, जिसके कारण मैं पर https://msdn.microsoft.com/en-us/library/cc716729(v=vs.110).aspx आधार पर निम्न,, भोली स्मार्ट नहीं है, लेकिन उपयोगी समारोह में लिखा था, है:

public static SqlDbType ConvertiTipo(Type giveType) 
    { 
     var typeMap = new Dictionary<Type, SqlDbType>(); 

     typeMap[typeof(string)] = SqlDbType.NVarChar; 
     typeMap[typeof(char[])] = SqlDbType.NVarChar; 
     typeMap[typeof(int)] = SqlDbType.Int; 
     typeMap[typeof(Int32)] = SqlDbType.Int; 
     typeMap[typeof(Int16)] = SqlDbType.SmallInt; 
     typeMap[typeof(Int64)] = SqlDbType.BigInt; 
     typeMap[typeof(Byte[])] = SqlDbType.VarBinary; 
     typeMap[typeof(Boolean)] = SqlDbType.Bit; 
     typeMap[typeof(DateTime)] = SqlDbType.DateTime2; 
     typeMap[typeof(DateTimeOffset)] = SqlDbType.DateTimeOffset; 
     typeMap[typeof(Decimal)] = SqlDbType.Decimal; 
     typeMap[typeof(Double)] = SqlDbType.Float; 
     typeMap[typeof(Decimal)] = SqlDbType.Money; 
     typeMap[typeof(Byte)] = SqlDbType.TinyInt; 
     typeMap[typeof(TimeSpan)] = SqlDbType.Time; 

     return typeMap[(giveType)]; 
    } 

कोई कैसे एक क्लीनर, बेहतर और अच्छा तरीका में एक ही परिणाम प्राप्त करने के लिए करने के विचार है?

+2

बनाना शब्दकोश रूपांतरण ठीक है। जीवन काल में * एक बार * हो गया। :) (कम परिवर्तन है) – Ian

+0

अगर मेरे उत्तर ने आपकी मदद की है, तो कृपया इसे अपने चुने हुए उत्तर के रूप में चिह्नित करें। :) –

उत्तर

13

आपका दृष्टिकोण एक अच्छी शुरुआत है, लेकिन यह दर्शाता है कि डिक्शनरी केवल एक बार किया जाना चाहिए, क्योंकि इयान एक टिप्पणी में कहता है।

, एक GIST यहाँ है कि एक ही विचार पर आधारित है नहीं है, हालांकि यह प्रकार के एक ही सेट के बीच परिवर्तित नहीं करता: https://gist.github.com/abrahamjp/858392

चेतावनी

मैं नीचे a working example है, लेकिन आप की जरूरत है यह पता होना चाहिए कि इस दृष्टिकोण में कुछ समस्याएं हैं। उदाहरण के लिए:

  • एक string के लिए, कैसे आप Char, NChar, VarChar, NVarChar, Text या NTextके बीच सही एक चुनना है (या यहां तक ​​कि Xml, हो सकता है)?
  • और byte[] जैसे ब्लब्स के लिए, क्या आपको Binary, VarBinary या Image का उपयोग करना चाहिए?
  • decimal, float और double के लिए, आप Decimal, Float, Money, SmallMoney या Real के लिए जाना चाहिए?
  • DateTime के लिए, आपको DateTime2, DateTimeOffset, DateTime, या SmallDateTime की आवश्यकता है?
  • क्या आप Nullable प्रकारों का उपयोग कर रहे हैं, जैसे int?? उन लोगों को सबसे अधिक SqlDbType अंतर्निहित प्रकार के रूप में देना चाहिए।

इसके अलावा, केवल Type प्रदान करने से आपको फ़ील्ड आकार और सटीकता जैसी अन्य बाधाओं के बारे में कुछ भी नहीं बताया जाता है। सही निर्णय लेना इस बारे में भी है कि आपके एप्लिकेशन में डेटा का उपयोग कैसे किया जाता है और यह डेटाबेस में कैसे संग्रहीत किया जाता है।

सबसे अच्छी बात यह है कि वास्तव में ORM इसे आपके लिए करें।

var sqlDbType = SqlHelper.GetDbType<string>(); 
// or: 
var sqlDbType = SqlHelper.GetDbType(typeof(DateTime?)); 
// or: 
var sqlDbType = SqlHelper.GetDbType(property.PropertyType); 
+1

अच्छा लग रहा है! मैं केवल यह देखने के लिए एक चेक जोड़ूंगा कि शब्द मौजूद है ('ContainsKey') शब्दकोश में मौजूद है और यदि डिफ़ॉल्ट' KeyNotFoundException' के बजाय अपने स्वयं के विस्तृत संदेश के साथ 'NotSupportedException' (या कस्टम अपवाद) नहीं फेंकता है। यह बाद में आसान समस्या निवारण के लिए बना सकता है यदि कोई समर्थित प्रकार कभी भी पास नहीं हुआ है। – Igor

+1

टिप के लिए धन्यवाद। मैंने 'ArgumentException' को फेंकने के लिए उत्तर संपादित किया है, क्योंकि इस प्रकार की चीज़ के लिए 'NotSupportedException' का अर्थ नहीं है। –

0

संपादित करें::

कोड

public static class SqlHelper 
{ 
    private static Dictionary<Type, SqlDbType> typeMap; 

    // Create and populate the dictionary in the static constructor 
    static SqlHelper() 
    { 
     typeMap = new Dictionary<Type, SqlDbType>(); 

     typeMap[typeof(string)]   = SqlDbType.NVarChar; 
     typeMap[typeof(char[])]   = SqlDbType.NVarChar; 
     typeMap[typeof(byte)]   = SqlDbType.TinyInt; 
     typeMap[typeof(short)]   = SqlDbType.SmallInt; 
     typeMap[typeof(int)]   = SqlDbType.Int; 
     typeMap[typeof(long)]   = SqlDbType.BigInt; 
     typeMap[typeof(byte[])]   = SqlDbType.Image; 
     typeMap[typeof(bool)]   = SqlDbType.Bit; 
     typeMap[typeof(DateTime)]  = SqlDbType.DateTime2; 
     typeMap[typeof(DateTimeOffset)] = SqlDbType.DateTimeOffset; 
     typeMap[typeof(decimal)]  = SqlDbType.Money; 
     typeMap[typeof(float)]   = SqlDbType.Real; 
     typeMap[typeof(double)]   = SqlDbType.Float; 
     typeMap[typeof(TimeSpan)]  = SqlDbType.Time; 
     /* ... and so on ... */ 
    } 

    // Non-generic argument-based method 
    public static SqlDbType GetDbType(Type giveType) 
    { 
     // Allow nullable types to be handled 
     giveType = Nullable.GetUnderlyingType(giveType) ?? giveType; 

     if (typeMap.ContainsKey(giveType)) 
     { 
      return typeMap[giveType]; 
     } 

     throw new ArgumentException($"{giveType.FullName} is not a supported .NET class"); 
    } 

    // Generic version 
    public static SqlDbType GetDbType<T>() 
    { 
     return GetDbType(typeof(T)); 
    } 
} 

और यह कैसे आप इसका इस्तेमाल होता है के बारे में मैं सोच रहा था और इस System.Data.SqlTypes प्रकार के लिए काम करता है।अगर मैं भविष्य में किसी की मदद करता हूं तो मैं इसे यहां छोड़ दूंगा।

मैं कुछ इस तरह करते हैं:

object objDbValue = DbReader.GetValue(columnIndex); 
Type sqlType = DbReader.GetFieldType(columnIndex); 
Type clrType = null; 

if (sqlType.Name.StartsWith("Sql")) 
{ 
    var objClrValue = objDbValue.GetType() 
           .GetProperty("Value") 
           .GetValue(objDbValue, null); 
    clrType = objClrValue.GetType(); 
} 

क्योंकि हर SqlDbType एक .Value संपत्ति जो वास्तविक अंतर्निहित CLR प्रकार मैं प्रतिबिंब का उपयोग इसे पाने के लिए है। यह बहुत बुरा है SqlDbType में कुछ इंटरफ़ेस नहीं है जो इसे पकड़ लेगा। वैल्यू प्रॉपर्टी और प्रतिबिंब की आवश्यकता नहीं होगी।
यह सही नहीं है लेकिन आपको एक शब्दकोश को मैन्युअल रूप से बनाने, बनाए रखने या पॉप्युलेट करने की आवश्यकता नहीं है। आप केवल मौजूदा प्रकार के एक प्रकार को देख सकते हैं, और यदि यह अस्तित्व में नहीं है तो मैपिंग को स्वचालित रूप से जोड़ने के लिए ऊपरी विधि का उपयोग करें। बहुत अधिक ऑटो-जनरेटेड।
भविष्य में SQL सर्वर को प्राप्त होने वाले किसी भी नए प्रकार का भी ख्याल रखता है।

+0

"संपादित: यह सुनिश्चित नहीं है कि मैं कहां टिप्पणी कर रहा था।" आह, आप सही हैं, दूसरी दिशा के लिए मेरे पास पूर्व-जनसंख्या वाले शब्दकोश की तुलना में बेहतर उत्तर नहीं है। हालांकि आम तौर पर उपयोग का मामला एसक्यूएल प्रकार से क्लियर प्रकार से होता है क्योंकि एक वर्ग प्रकार एकाधिक क्लियर प्रकारों को मैप कर सकता है। –

+0

ऐसा लगता है [SqlDbType] (https://msdn.microsoft.com/en-us/library/system.data.sqldbtype (v = vs.110) .aspx) एक गणना है इसलिए मुझे यकीन नहीं है कि यह अतिरिक्त कैसे रखता है सीएलआर प्रकार के बारे में जानकारी। प्रश्न बनाने के लिए यह काम नहीं करेगा, केवल एक क्वेरी से सही सीएलआर प्रकार के परिणामों का अनुवाद करने के लिए। – Igor

+0

क्षमा करें, मैंने तुरंत अपनी टिप्पणी हटा दी क्योंकि मैं थोड़ा सा पुनर्विचार करना चाहता था। मेरी प्रारंभिक टिप्पणी थी * "क्या यह विपरीत दिशा नहीं जाती है?" *। अब मैं @ इगोर के साथ अधिक हूं, क्योंकि वांछित 'एसकएलडीबी टाइप 'एक गणना है। –

0

ऐसा लगता है कि लुकअप तालिका की इस तरह पहले से ही उपलब्ध है, यद्यपि नहीं System.Data (या .Object या .Type) में बल्कि System.Web में।

परियोजना -> संदर्भ जोड़ें -> System.Web -> ठीक

फिर https://msdn.microsoft.com/en-us/library/system.data.sqldbtype(v=vs.110).aspx भी कहते हैं

आदेश मानकों की स्थापना करते हैं, SqlDbType और DbType जुड़े हुए हैं। इसलिए, डीबीटाइप सेट करने से SqlDbType को एक सहायक SqlDbType में बदल दिया जाता है।

तो, यह सैद्धांतिक रूप से काम करना चाहिए;)

using Microsoft.SqlServer.Server; // SqlDataRecord and SqlMetaData 
using System; 
using System.Collections; // IEnumerator and IEnumerable 
using System.Collections.Generic; // general IEnumerable and IEnumerator 
using System.Data; // DataTable and SqlDataType 
using System.Data.SqlClient; // SqlConnection, SqlCommand, and SqlParameter 
using System.Web.UI.WebControls; // for Parameters.Convert... functions 

private static SqlDbType TypeToSqlDbType(Type t) { 
    DbType dbtc = Parameters.ConvertTypeCodeToDbType(t.GetTypeCodeImpl()); 
    SqlParameter sp = new SqlParameter(); 
    // DbParameter dp = new DbParameter(); 
    // dp.DbType = dbtc; 
    sp.DbType = dbtc; 
    return sp.SqlDbType; 
} 
संबंधित मुद्दे