2009-02-07 17 views
14

वस्तुओं की एक सूची को देखते हुए, मुझे इसे एक डेटासेट में बदलने की आवश्यकता है जहां सूची में प्रत्येक आइटम को एक पंक्ति द्वारा दर्शाया जाता है और प्रत्येक संपत्ति पंक्ति में एक स्तंभ है। रिपोर्ट के रूप में Excel दस्तावेज़ बनाने के लिए यह डेटासेट को Aspose.Cells फ़ंक्शन पर पास कर दिया जाएगा।मैं एक डेटासेट में सूची <T> सूची कैसे बदलूं?

ID Status Message 
1 true "message" 
2 false "message2" 
3 true "message3" 
... 

पल केवल एक चीज मैं के बारे में सोच सकते हैं पर:

public class Record 
{ 
    public int ID { get; set; } 
    public bool Status { get; set; } 
    public string Message { get; set; } 
} 

एक सूची रिकॉर्ड को देखते हुए, मैं इसे कैसे एक डेटासेट में इस प्रकार के रूप में परिणत करते हैं:

मैं निम्नलिखित है कहो निम्नानुसार है:

DataSet ds = new DataSet 
ds.Tables.Add(); 
ds.Tables[0].Add("ID", typeof(int));  
ds.Tables[0].Add("Status", typeof(bool)); 
ds.Tables[0].Add("Message", typeof(string)); 

foreach(Record record in records) 
{ 
    ds.Tables[0].Rows.Add(record.ID, record.Status, record.Message); 
} 

लेकिन इस तरह से मुझे लगता है कि वहां से बेहतर तरीका होना चाहिए क्योंकि बहुत कम यदि नए गुण रिकॉर्ड में जोड़े जाते हैं तो वे डेटासेट में दिखाई नहीं देंगे ... लेकिन साथ ही यह मुझे प्रत्येक संपत्ति को पंक्ति में जोड़े जाने वाले ऑर्डर को नियंत्रित करने की अनुमति देता है।

क्या कोई इसे करने के बेहतर तरीके से जानता है?

उत्तर

27

आप इसे अंतर्निहित प्रकार के गुणों का निरीक्षण करते हुए प्रतिबिंब और जेनेरिक के माध्यम से कर सकते हैं।

public static DataTable ToDataTable<T>(this IEnumerable<T> collection) 
    { 
     DataTable dt = new DataTable("DataTable"); 
     Type t = typeof(T); 
     PropertyInfo[] pia = t.GetProperties(); 

     //Inspect the properties and create the columns in the DataTable 
     foreach (PropertyInfo pi in pia) 
     { 
      Type ColumnType = pi.PropertyType; 
      if ((ColumnType.IsGenericType)) 
      { 
       ColumnType = ColumnType.GetGenericArguments()[0]; 
      } 
      dt.Columns.Add(pi.Name, ColumnType); 
     } 

     //Populate the data table 
     foreach (T item in collection) 
     { 
      DataRow dr = dt.NewRow(); 
      dr.BeginEdit(); 
      foreach (PropertyInfo pi in pia) 
      { 
       if (pi.GetValue(item, null) != null) 
       { 
        dr[pi.Name] = pi.GetValue(item, null); 
       } 
      } 
      dr.EndEdit(); 
      dt.Rows.Add(dr); 
     } 
     return dt; 
    } 
+0

ठीक है, समुदाय ने बात की है इसलिए मैं इसे एक जवाब दूंगा, भले ही मैं इसे अपने उद्देश्यों के लिए उपयोग नहीं कर पाऊंगा क्योंकि मैं पैरामीटर के क्रम को नियंत्रित करने में सक्षम होना चाहता हूं। लेकिन मैं निश्चित रूप से इस समाधान को ध्यान में रखूंगा ... – mezoid

+2

अरे, मैंने अभी आपके एक्सटेंशन का परीक्षण किया है और पाया है कि यदि आप ऑर्डर को नियंत्रित करना चाहते हैं तो स्तंभ डेटाटेबल में दिखाई देते हैं तो आपको उन्हें क्रम में घोषित करने की आवश्यकता है उन्हें टाइप टी के ऑब्जेक्ट में चाहते हैं जिसे आप एक्सटेंशन में पास करते हैं। वह तो कमाल है! – mezoid

1

अतिरिक्त गुण जोड़ने के लिए कक्षा Record के गुणों को निर्धारित करने के लिए Reflection का उपयोग करने के अलावा, यह बहुत अधिक है।

+0

में इस एक्सटेंशन का उपयोग करने तुम शायद सही हो ... यहां तक ​​कि इसकी नहीं है कि मैं क्या सुनना चाहते थे, हालांकि। मुझे लगता है कि या तो मुझे डेटासेट्स के अपने ज्ञान को सुधारने की जरूरत है या माइक्रोसॉफ्ट में किसी को बेहतर तरीके से सोचने की जरूरत है। – mezoid

0

मैं इस कार्य को पूरा करने के लिए एक छोटा सा पुस्तकालय अपने आप को लिखा है:

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

इसकी चमक तेज है। आप इसे यहाँ पा सकते हैं: ModelShredder on GoogleCode

0

मैं मामले को संभालने के लिए जब List आदिम शामिल है या String तत्वों सीएमएस 'एक्सटेंशन विधि में कुछ परिवर्तन किए। उस स्थिति में परिणामस्वरूप DataTable में केवल Column होगा जिसमें सूची में प्रत्येक मान के लिए होगा।

पहले मैंने सभी मूल्य प्रकारों (न केवल आदिम प्रकारों) को शामिल करने के बारे में सोचा था, लेकिन मैं नहीं चाहता था कि संरचनाएं (जो मूल्य प्रकार हैं) शामिल हों।

यह परिवर्तन एक List(Of Long), या List<long>, परिवर्तित एक DataTable में एक एमएस एसक्यूएल 2008 संग्रहित प्रक्रिया में एक टेबल-वैल्यूड पैरामीटर के रूप में उपयोग करने के लिए की मेरी जरूरत से पड़ी।

मुझे खेद है कि मेरा कोड वीबी में है, भले ही यह प्रश्न टैग किया गया हो; मेरी परियोजना वीबी में है (मेरी पसंद नहीं है) और सी # में बदलावों को लागू करना मुश्किल नहीं होना चाहिए।

Imports System.Runtime.CompilerServices 
Imports System.Reflection 

Module Extensions 

    <Extension()> 
    Public Function ToDataTable(Of T)(ByVal collection As IEnumerable(Of T)) As DataTable 
     Dim dt As DataTable = New DataTable("DataTable") 
     Dim type As Type = GetType(T) 
     Dim pia() As PropertyInfo = type.GetProperties() 

     ' For a collection of primitive types create a 1 column DataTable 
     If type.IsPrimitive OrElse type.Equals(GetType(String)) Then 
      dt.Columns.Add("Column", type) 
     Else 
      ' Inspect the properties and create the column in the DataTable 
      For Each pi As PropertyInfo In pia 
       Dim ColumnType As Type = pi.PropertyType 
       If ColumnType.IsGenericType Then 
        ColumnType = ColumnType.GetGenericArguments()(0) 
       End If 
       dt.Columns.Add(pi.Name, ColumnType) 
      Next 

     End If 

     ' Populate the data table 
     For Each item As T In collection 
      Dim dr As DataRow = dt.NewRow() 
      dr.BeginEdit() 
      ' Set item as the value for the lone column on each row 
      If type.IsPrimitive OrElse type.Equals(GetType(String)) Then 
       dr("Column") = item 
      Else 
       For Each pi As PropertyInfo In pia 
        If pi.GetValue(item, Nothing) <> Nothing Then 
         dr(pi.Name) = pi.GetValue(item, Nothing) 
        End If 
       Next 
      End If 
      dr.EndEdit() 
      dt.Rows.Add(dr) 
     Next 
     Return dt 
    End Function 

End Module 
0

मुझे यह कोड माइक्रोसॉफ्ट मंच पर मिला। यह अब तक का सबसे आसान तरीका है, समझने और उपयोग करने में आसान है। इसने मुझे घंटे बचा लिया है। मैंने इसे वास्तविक कार्यान्वयन में किसी भी बदलाव के बिना एक्सटेंशन विधि के रूप में अनुकूलित किया है। नीचे कोड है। इसे ज्यादा स्पष्टीकरण की आवश्यकता नहीं है।

आप एक ही कार्यान्वयन

1) सार्वजनिक स्थिर डेटासेट ToDataSetFromObject (इस वस्तु dsCollection)

2) सार्वजनिक स्थिर डेटासेट ToDataSetFromArrayOfObject (इस वस्तु [] arrCollection) के साथ दो समारोह हस्ताक्षर का उपयोग कर सकते हैं। मैं नीचे दिए गए उदाहरण में इसका उपयोग करूँगा।

// <summary> 
// Serialize Object to XML and then read it into a DataSet: 
// </summary> 
// <param name="arrCollection">Array of object</param> 
// <returns>dataset</returns> 

public static DataSet ToDataSetFromArrayOfObject(this object[] arrCollection) 
{ 
    DataSet ds = new DataSet(); 
    try { 
     XmlSerializer serializer = new XmlSerializer(arrCollection.GetType); 
     System.IO.StringWriter sw = new System.IO.StringWriter(); 
     serializer.Serialize(sw, dsCollection); 
     System.IO.StringReader reader = new System.IO.StringReader(sw.ToString()); 
     ds.ReadXml(reader); 
    } catch (Exception ex) { 
     throw (new Exception("Error While Converting Array of Object to Dataset.")); 
    } 
    return ds; 
} 

कोड

Country[] objArrayCountry = null; 
objArrayCountry = ....;// populate your array 
if ((objArrayCountry != null)) { 
    dataset = objArrayCountry.ToDataSetFromArrayOfObject(); 
} 

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

  • कोई संबंधित समस्या नहीं^_^