2009-11-27 16 views
5

मेरे आवेदन में मुझे विभिन्न संग्रहीत प्रक्रियाओं द्वारा रिकॉर्ड किए गए रिकॉर्ड की एक सूची प्रदर्शित करने की आवश्यकता है। प्रत्येक स्टोर प्रक्रिया विभिन्न प्रकार के रिकॉर्ड लौटाती है (यानी कॉलम की संख्या और कॉलम प्रकार अलग हैं)।सी # फ़ंक्शन सामान्य वस्तुओं/इकाइयों को वापस करने के लिए

मेरा मूल विचार प्रत्येक प्रकार के रिकॉर्ड के लिए एक वर्ग बनाना था और एक ऐसा फ़ंक्शन बनाना था जो संबंधित संग्रहीत प्रक्रिया को निष्पादित करेगा और सूची < MyCustomClass> वापस कर देगा। कुछ इस तरह:

public class MyCustomClass1 
    { 
     public int Col1 { get; set; } //In reality the columns are NOT called Col1 and Col1 but have proper names 
     public int Col2 { get; set; } 
    } 

    public static List<MyCustomClass1> GetDataForReport1(int Param1) 
    { 

     List<MyCustomClass1> output = new List<MyCustomClass1>(); 

     using (SqlConnection cn = new SqlConnection("MyConnectionString")) 
     using (SqlCommand cmd = new SqlCommand("MyProcNameForReport1", cn)) 
     { 
      cmd.CommandType = CommandType.StoredProcedure; 
      cmd.Parameters.Add("@Param1", SqlDbType.Int).Value = Param1; 

      SqlDataReader rdr=cmd.ExecuteReader(); 

      int Col1_Ordinal = rdr.GetOrdinal("Col1"); 
      int Col2_Ordinal = rdr.GetOrdinal("Col2"); 

      while (rdr.Read()) 
      { 
         output.Add(new MyCustomClass1 
         { 
          Col1 = rdr.GetSqlInt32(Col1_Ordinal).Value, 
          Col2 = rdr.GetSqlInt32(Col2_Ordinal).Value 
         }); 
      } 
      rdr.Close(); 
      } 

     return output; 

    } 

यह ठीक काम करता है, लेकिन जैसा कि मैं अपने ग्राहक कोड में उन रिकॉर्ड में हेरफेर करने की जरूरत नहीं है (मैं सिर्फ उन्हें अपने आवेदन परत में एक चित्रमय नियंत्रण करने के लिए बाध्य करने की जरूरत है) यह वास्तव में नहीं है ऐसा करने के लिए समझदारी करें क्योंकि मैं बहुत से कस्टम वर्गों के साथ समाप्त होता हूं जिसका मैं वास्तव में उपयोग नहीं करता।

public static DataTable GetDataForReport1(int Param1) 
    { 

     DataTable output = new DataTable(); 

     using (SqlConnection cn = new SqlConnection("MyConnectionString")) 
     using (SqlCommand cmd = new SqlCommand("MyProcNameForReport1", cn)) 
     { 
      cmd.CommandType = CommandType.StoredProcedure; 
      cmd.Parameters.Add("@Param1", SqlDbType.Int).Value = Param1; 

      output.Load(cmd.ExecuteReader()); 
     } 

     return output; 

    } 

यह एक DataTable जो मैं जो कुछ भी नियंत्रण मैं अपने अनुप्रयोग परत में उपयोग करने के लिए बाध्य कर सकते हैं देता है: मैं इस जो करता है चाल पाया। मैं सोच रहा हूं कि डेटाटेबल का उपयोग करना वास्तव में जरूरी है।

public static List<object> GetDataForReport1(int Param1) 
    { 

     List<object> output = new List<object>(); 

     using (SqlConnection cn = new SqlConnection("MyConnectionString")) 
     using (SqlCommand cmd = new SqlCommand("MyProcNameForReport1", cn)) 
     { 
      cmd.CommandType = CommandType.StoredProcedure; 
      cmd.Parameters.Add("@Param1", SqlDbType.Int).Value = Param1; 

      SqlDataReader rdr=cmd.ExecuteReader(); 

      int Col1_Ordinal = rdr.GetOrdinal("Col1"); 
      int Col2_Ordinal = rdr.GetOrdinal("Col2"); 

      while (rdr.Read()) 
      { 
         output.Add(new 
         { 
          Col1 = rdr.GetSqlInt32(Col1_Ordinal).Value, 
          Col2 = rdr.GetSqlInt32(Col2_Ordinal).Value 
         }); 
      } 
      rdr.Close(); 
      } 

     return output; 

    } 

किसी भी अन्य विचार:

मैं वस्तुओं की एक सूची गुमनाम वर्गों का उपयोग कर बनाया नहीं लौट सकते हैं? असल में मैं सिर्फ फ़ंक्शन को 'कुछ' वापस करने के लिए चाहता हूं जिसे मैं एक ग्राफिकल नियंत्रण से जोड़ सकता हूं और मैं कस्टम कक्षाएं बनाना नहीं चाहता क्योंकि वे वास्तव में उपयोग नहीं किए जाएंगे। सबसे अच्छा तरीका क्या होगा?

+1

बीटीडब्ल्यू, एसक्लडाटा रीडर के लिए सबसे अच्छा अभ्यास उपयोग की अगली शैली है: (var rdr = cmd.ExecuteReader() {जबकि (rdr.Read() {..}} - तो यह स्वचालित रूप से बंद हो जाएगा (डिस्प्ले) – abatishchev

+0

अच्छी तरह से देखा गया। – Anthony

उत्तर

4

अच्छी खबर यह है: यह पहली बार नहीं है कि entities vs datasets समस्या आ गई है। यह मेरे खुद के प्रोग्रामिंग अनुभव से बहुत पुराना बहस है। यदि आप डीटीओ या कस्टम इकाइयों को नहीं लिखना चाहते हैं तो आपके विकल्प डेटाटेबल्स/डेटासेट्स हैं या आप फिर से इस व्हील को फिर से शुरू कर सकते हैं। आप पहले नहीं होंगे और आप अंतिम नहीं होंगे। डीटीओ/संस्थाओं के लिए तर्क यह है कि आपके पास डेटासेट्स के साथ प्राप्त प्रदर्शन ओवरहेड नहीं हैं। डेटासेट्स को विभिन्न कॉलम, आदि के डेटाटाइप के बारे में बहुत सारी जानकारी संग्रहीत करनी है ...

एक बात, आपको यह सुनकर खुशी हो सकती है कि यदि आप कस्टम इकाई मार्ग पर जाते हैं और आप अपनी ऑब्जेक्ट के लिए खुश हैं आपके स्पॉक्स द्वारा दिए गए कॉलम नामों से मेल खाने के लिए संपत्ति के नाम, आप उन सभी GetDataForReport() मैपिंग फ़ंक्शंस को लिखना छोड़ सकते हैं जहां आप गुणों के लिए कॉलम मैप करने के लिए GetOrdinal का उपयोग कर रहे हैं। सौभाग्य से, कुछ स्मार्ट बंदरों ने ठीक से उस मुद्दे को here पर मुकदमा दायर किया है।

संपादित करें: मैं एक बिल्कुल अलग समस्या आज शोध किया गया था (बाध्यकारी Silverlight datagrids के लिए डेटासेट) और व्लादिमीर Bodurov, से पता चलता है जो डायनामिक रूप से तैयार वस्तुओं (आईएल का प्रयोग करके) के एक IEnumerable को IDictionary की एक IEnumerable को बदलने के लिए कैसे द्वारा this article बारे में जाना। यह मेरे लिए हुआ कि आप गतिशील संग्रहों के मुद्दे को हल करने के लिए IDictionary के IENumerable की बजाय एक डेटाटेडर को स्वीकार करने के लिए विस्तार विधि को आसानी से संशोधित कर सकते हैं। यह बहुत अच्छा है। मुझे लगता है कि यह वास्तव में पूरा करेगा जो आप बाद में कर रहे थे कि अब आपको डेटासेट या कस्टम इकाइयों की आवश्यकता नहीं है।असल में आप कस्टम इकाई संग्रह के साथ समाप्त होते हैं लेकिन आप वास्तविक कक्षाओं को लिखने के ऊपरी हिस्से को खो देते हैं।

आप आलसी हैं, तो यहां एक विधि है कि व्लादिमीर शब्दकोश संग्रह में किसी DataReader बदल जाता है (यह वास्तव में अपने विस्तार विधि परिवर्तित करने की तुलना में कम कुशल है):

public static IEnumerable<IDictionary> ToEnumerableDictionary(this IDataReader dataReader) 
{ 
    var list = new List<Dictionary<string, object>>(); 
    Dictionary<int, string> keys = null; 
    while (dataReader.Read()) 
    { 
     if(keys == null) 
     { 
      keys = new Dictionary<int, string>(); 
      for (var i = 0; i < dataReader.FieldCount; i++) 
       keys.Add(i, dataReader.GetName(i)); 
     } 
     var dictionary = keys.ToDictionary(ordinalKey => ordinalKey.Value, ordinalKey => dataReader[ordinalKey.Key]); 
     list.Add(dictionary); 
    } 
    return list.ToArray(); 
} 
+0

मैं देखता हूं कि आपका क्या मतलब है, लेकिन मेरा सवाल है, मुझे लगता है, कहीं बीच में है। यह सिर्फ 'मुझे कस्टम संस्थाओं या डेटासेट की सूची वापस नहीं करनी चाहिए'। मैं यह भी उल्लेख कर रहा था कि मैं सामान्य वस्तुओं की एक सूची वापस कर सकता हूं (सूची < object >)। इस तरह यह कस्टम इकाइयों की एक सूची नहीं होगी लेकिन यह डेटासेट नहीं होगा। – Anthony

+0

यदि आप .NET 4 का उपयोग कर रहे हैं तो आप एक सूची का उपयोग करने में सक्षम हो सकते हैं। ई आपकी गतिशीलता वास्तव में एक्सपांडो ऑब्जेक्ट्स (http://bit.ly/TDzbN) हैं। – grenade

+0

लेख के लिंक के लिए धन्यवाद। ऐसा लगता है कि यह वही है जो मुझे चाहिए और यह वास्तव में एक समाधान प्रदान करेगा जो 'इकाई या डेटासेट' नहीं है। मैं दुर्भाग्य से .NET 4 का उपयोग नहीं कर रहा हूं लेकिन मैं यह दिमाग रखूंगा। – Anthony

1

यदि आप XmlSerialize करने जा रहे हैं और यह कुशल होना चाहते हैं, तो वे अज्ञात नहीं हो सकते हैं। क्या आप बदलाव वापस भेज रहे हैं? बेनामी वर्ग इसके लिए ज्यादा उपयोग नहीं करेंगे।

यदि आप वास्तव में इसे ग्रिडिफ़ाई करने के अलावा डेटा के साथ कुछ भी नहीं करने जा रहे हैं, तो डेटाटेबल आपके संदर्भ के लिए भी एक अच्छा जवाब हो सकता है।

सामान्य रूप से, यदि कोई भी प्रकार का रोचक व्यवसाय लॉगिन चल रहा है, तो आपको केवल ग्रिड के आसपास नौकायन करने के बजाय डेटा ट्रांसफर ऑब्जेक्ट्स का उपयोग करना चाहिए।

+0

कोई डेटा वापस नहीं बदला जा रहा है। अगर मैं डेटा टैंसर ऑब्जेक्ट का उपयोग करता हूं तो क्या यह कस्टम क्लास का उपयोग करने जैसा नहीं है? मुझे प्रत्येक प्रकार के रिकॉर्ड के लिए एक डीटीओ बनाना होगा – Anthony

0

आप गुमनाम वर्गों का उपयोग करते हैं, तो आप अभी भी एक परिभाषित कर रहे हैं प्रकार। टाइपिंग की मात्रा को कम करने के लिए आप बस टाइप इनफरेंस का उपयोग कर सकते हैं, और क्लास टाइप किसी भी नेमस्पेस को अव्यवस्थित नहीं करेगा।

यहां उनका उपयोग करने का नकारात्मक पक्ष यह है कि आप उन्हें विधि से बाहर करना चाहते हैं। जैसा कि आपने नोट किया है, ऐसा करने का एकमात्र तरीका उन्हें ऑब्जेक्ट्स में डालना है, जो उनके सभी डेटा प्रतिबिंब के बिना पहुंच योग्य बनाता है! क्या आप कभी भी इस डेटा के साथ कोई प्रसंस्करण या गणना करने जा रहे हैं? कॉलम में से किसी एक को मूल्य के बजाय चित्र के रूप में प्रदर्शित करें, या इसे किसी शर्त के आधार पर छुपाएं? यहां तक ​​कि यदि आप कभी भी एक सशर्त बयान प्राप्त करने वाले हैं, तो अनाम वर्ग संस्करण के साथ ऐसा करने से आप चाहेंगे कि आप नहीं चाहते थे।

संबंधित मुद्दे

 संबंधित मुद्दे