2011-08-19 11 views
5

मैंने बैच ऑपरेशंस के लिए SQL सर्वर 2k8 में तालिका मानित पैरामीटर्स का उपयोग शुरू कर दिया है। मुझे इस सुविधा को बहुत पसंद आया और मुझे लगता है कि यह लंबे इंतजार के बाद आया था।.NET मदद में प्रतिबिंब उपयोगकर्ता परिभाषित टाइपनाम को देखकर एक तालिका मूल्यवान पैरामीटर/SqlMetaData [] ऑब्जेक्ट गतिशील रूप से निर्माण कर सकता है?

हालांकि, .NET कोड से एक टीवीपी पास करने के लिए एसक्यूएलएमटाडेटा [] बनाने और फिर लूप में मान भरने में बहुत अधिक कठिनाई शामिल है।

सिंक्रनाइज़ेशन में अपने .NET कोड में SQL सर्वर और SQLMetaData [] ऑब्जेक्ट्स में उपयोगकर्ता परिभाषित प्रकार को रखने के रखरखाव से कैसे बचते हैं? जब मैं एसक्यूएल में एक प्रकार की परिभाषा बदलता हूं, तो मुझे यह जानने का कोई आसान तरीका नहीं है कि मैंने उस प्रकार का उपयोग बड़े पैमाने पर .NET में किया था।

कर सकते हैं .Net प्रतिबिंब उपयोगकर्ता परिभाषित प्रकार का नाम देकर और SQL arrays प्रदान करके डेटा भरने में SQLMetadata बनाने के लिए प्रोग्रामर को सहेज सकता है।

SqlMetaData[] tvp_TradingAllocationRule = new SqlMetaData[13]; 
try 
{ 
    tvp_TradingAllocationRule[0] = new SqlMetaData("ID", SqlDbType.UniqueIdentifier); 
    tvp_TradingAllocationRule[1] = new SqlMetaData("Name", SqlDbType.VarChar, 255); 
    tvp_TradingAllocationRule[2] = new SqlMetaData("Description", SqlDbType.VarChar, -1); 
    tvp_TradingAllocationRule[3] = new SqlMetaData("Enabled", SqlDbType.Bit); 
    tvp_TradingAllocationRule[4] = new SqlMetaData("Category", SqlDbType.VarChar, 255); 
    tvp_TradingAllocationRule[5] = new SqlMetaData("Custom1", SqlDbType.VarChar, 255); 
    tvp_TradingAllocationRule[6] = new SqlMetaData("Custom2", SqlDbType.VarChar, 255); 
    tvp_TradingAllocationRule[7] = new SqlMetaData("Custom3", SqlDbType.VarChar, 255); 
    tvp_TradingAllocationRule[8] = new SqlMetaData("CreatedBy", SqlDbType.VarChar, 20); 
    tvp_TradingAllocationRule[9] = new SqlMetaData("CreatedTS", SqlDbType.DateTime); 
    tvp_TradingAllocationRule[10] = new SqlMetaData("ModifiedBy", SqlDbType.VarChar, 20); 
    tvp_TradingAllocationRule[11] = new SqlMetaData("ModifiedTS", SqlDbType.DateTime); 
    tvp_TradingAllocationRule[12] = new SqlMetaData("IsFactory", SqlDbType.Bit); 
} 
catch (Exception ex) 
{ 
    throw new Exception("Error Defining the tvp_TradingActionCondition in .Net" + ex.Message); 
} 

foreach (TradingRuleMetadata ruleMetadata in updatedRules) 
{ 
    SqlDataRecord tradingAllocationRule = new SqlDataRecord(tvp_TradingAllocationRule); 
    try 
    { 
     tradingAllocationRule.SetGuid(0, ruleMetadata.ID); 
     tradingAllocationRule.SetString(1, ruleMetadata.Name); 
     tradingAllocationRule.SetString(2, ruleMetadata.Description); 
     tradingAllocationRule.SetBoolean(3, ruleMetadata.Enabled); 
     tradingAllocationRule.SetString(4, ruleMetadata.Category); 
     tradingAllocationRule.SetString(5, ruleMetadata.Custom1); 
     tradingAllocationRule.SetString(6, ruleMetadata.Custom2); 
     tradingAllocationRule.SetString(7, ruleMetadata.Custom3); 
     tradingAllocationRule.SetString(8, ruleMetadata.CreatedBy); 
     tradingAllocationRule.SetDateTime(9, ruleMetadata.CreatedDate); 
     tradingAllocationRule.SetString(10, ruleMetadata.ModifiedBy); 
     tradingAllocationRule.SetDateTime(11, ruleMetadata.ModifiedDate); 
     tradingAllocationRule.SetBoolean(12, ruleMetadata.IsFactory); 
     tvp_TradingAllocationRuleRecords.Add(tradingAllocationRule); 
    } 
    catch (Exception ex) 
    { 

    } 
} 

अब अगर अपनी मेज 100 स्तंभ होते हैं, अपने कोड की कल्पना:

इस उदाहरण पर विचार करें।

+0

मेरा उत्तर हटाया गया, यह बहुत उपयोगी नहीं है। आप .net –

+0

में डायनामिक डेटा प्रकार की जांच करना चाहेंगे, क्या आप वर्तमान में उपयोग किए जा रहे कोड का नमूना दिखा सकते हैं? – svick

+0

@svic: आपके लिए एक नमूना कोड पोस्ट किया गया ... – vinayvasyani

उत्तर

0

कोड नमूना देने के लिए प्रश्न में पर्याप्त नहीं है, लेकिन इस तरह के कुछ के लिए मैं कुछ अलग करता हूं जैसे एसक्यूएल मेटाडेटा पढ़ने और सहायक वर्ग उत्पन्न करने के लिए निष्पादन योग्य .NET निष्पादन योग्य (आपके उदाहरण की तरह दिख रहा है) प्रत्येक यूडीटी के लिए। कोड पीढ़ी का लाभ यह है कि यह रन टाइम पर थोड़ा तेज़ है, और, सबसे महत्वपूर्ण बात यह है कि आप सोर्स कोड को पढ़ और पढ़ सकते हैं जैसे कि यह हाथ से लिखा गया था। यह विशेष रूप से करना मुश्किल नहीं है - विशेष रूप से अब आंशिक कीवर्ड मौजूद है।

3

आप प्रतिबिंब का उपयोग करके ऐसा कर सकते हैं। सबसे पहले, नाम और लंबाई के लिए डिफ़ॉल्ट मानों को ओवरराइड करने का एक तरीका होना चाहिए। ऐसा करने के लिए, को परिभाषित Attribute रों:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] 
class LengthAttribute : Attribute 
{ 
    private readonly int m_length; 
    public int Length 
    { 
     get { return m_length; } 
    } 

    public LengthAttribute(int length) 
    { 
     m_length = length; 
    } 
} 

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] 
class ColumnNameAttribute : Attribute 
{ 
    private readonly string m_name; 
    public string Name 
    { 
     get { return m_name; } 
    } 

    public ColumnNameAttribute(string name) 
    { 
     m_name = name; 
    } 
} 

और अपने प्रकार पर उन्हें इस्तेमाल:

:

class TradingRuleMetadata 
{ 
    public Guid ID { get; set; } 

    public string Name { get; set; } 

    [Length(-1)] 
    public string Description { get; set; } 

    public bool Enabled { get; set; } 

    public string Category { get; set; } 

    public string Custom1 { get; set; } 

    public string Custom2 { get; set; } 

    public string Custom3 { get; set; } 

    [Length(20)] 
    public string CreatedBy { get; set; } 

    [ColumnName("CreatedTS")] 
    public DateTime CreatedDate { get; set; } 

    [Length(20)] 
    public string ModifiedBy { get; set; } 

    [ColumnName("ModifiedTS")] 
    public DateTime ModifiedDate { get; set; } 

    public bool IsFactory { get; set; } 
} 

तो फिर तुम एक विधि है कि SqlDataRecord का संग्रह करने के लिए इस प्रकार का एक संग्रह नक्शे बना सकते हैं

private static readonly Dictionary<Type, SqlDbType> SqlDbTypes = 
    new Dictionary<Type, SqlDbType> 
    { 
     { typeof(Guid), SqlDbType.UniqueIdentifier }, 
     { typeof(string), SqlDbType.VarChar }, 
     { typeof(bool), SqlDbType.Bit }, 
     { typeof(DateTime), SqlDbType.DateTime } 
    }; 

static IList<SqlDataRecord> GetDataRecords<T>(IEnumerable<T> data) 
{ 
    Type type = typeof(T); 

    var properties = type.GetProperties(); 

    SqlMetaData[] metaData = new SqlMetaData[properties.Length]; 
    try 
    { 
     for (int i = 0; i < properties.Length; i++) 
     { 
      var property = properties[i]; 

      string name = property.Name; 
      var columnNameAttribute = GetAttribute<ColumnNameAttribute>(property); 
      if (columnNameAttribute != null) 
       name = columnNameAttribute.Name; 

      var dbType = SqlDbTypes[property.PropertyType]; 

      if (dbType == SqlDbType.VarChar) 
      { 
       int length = 255; 

       var lengthAttribute = GetAttribute<LengthAttribute>(property); 
       if (lengthAttribute != null) 
        length = lengthAttribute.Length; 

       metaData[i] = new SqlMetaData(name, dbType, length); 
      } 
      else 
       metaData[i] = new SqlMetaData(name, dbType); 
     } 
    } 
    catch (Exception ex) 
    { 
     throw new Exception(); 
    } 

    var records = new List<SqlDataRecord>(); 
    foreach (T item in data) 
    { 
     SqlDataRecord record = new SqlDataRecord(metaData); 
     try 
     { 
      var values = properties.Select(p => p.GetValue(item, null)).ToArray(); 
      record.SetValues(values); 
      records.Add(record); 
     } 
     catch (Exception ex) 
     { 

     } 
    } 
    return records; 
} 

static T GetAttribute<T>(PropertyInfo property) 
{ 
    return (T)property.GetCustomAttributes(typeof(T), true).SingleOrDefault(); 
} 

यह कोड काफी प्रतिबिंब का उपयोग करता है, इसलिए यह आपके लिए बहुत धीमा हो सकता है। यदि ऐसा है, तो आपको किसी प्रकार की कैशिंग लागू करने की आवश्यकता होगी। ऐसा करने का एक तरीका Expression बनाना होगा जो यह सब काम करता है और फिर इसे एक प्रतिनिधि में संकलित करता है (केवल 4, क्योंकि आपको BlockExpression की आवश्यकता होगी)।

इसके अलावा, आपकी वास्तविक आवश्यकताएं अधिक जटिल हो सकती हैं, क्योंकि आपको कुछ गुणों या कुछ इसी तरह की अनदेखी करने की आवश्यकता हो सकती है। लेकिन यह जोड़ना आसान होना चाहिए।