2011-01-04 12 views
5

पर fetch datarow लाने के लिए मेरे पास एक वर्ग आइटम है जो किसी सूची में किसी आइटम का प्रतिनिधित्व करता है। मेरे पास यह कार्य है जो संग्रहीत प्रक्रिया को कॉल करता है जो डेटाटेबल लौटाता है और मुझे डेटा के ऑरे में डेटाटेबल को कनवर्ट करने की आवश्यकता है।सी # ऑब्जेक्ट

public class Item 
{ 
    private string _ItemIdDataName = "item_id"; 
    private string _ItemNameDataName = "item_name"; 
    private string _PriceDataName = "price"; 

    public long ItemId { get; set; } 
    public string ItemName { get; set; } 
    public float Price { get; set; } 

    private Item(DataRow row) 
    { 
     if (row != null) 
     { 
      ItemId = long.Parse(row[_ItemIdDataName].ToString()); 
      ItemName = row[_ItemNameDataName].ToString(); 
      Price = float.Parse(row[_PriceDataName].ToString()); 
     } 
    } 

    public Item[] load() 
    { 
     DataTable dt=DBHandler.GetItems();//Stored procedure that returns DataTable 
     Item[] items = new Item[dt.Rows.Count]; 
     for (int i = 0; i < dt.Rows.Count; i++) 
     { 
      items[i] = new Item(dt.Rows[i]); 
     } 
     return items; 
    } 
} 

Am मैं इसे ठीक कर: यहाँ मैं क्या कर रहा है? मैं इसे कैसे सुधार सकता हूं?

+2

'लोड()' अंदर मद वर्ग क्यों है? –

+0

क्योंकि यह इसे विभिन्न वर्ग के तहत रखने के लिए बहुत मेहनतजनक लग रहा है। मेरे पास इस तरह के कई मामले हैं और मेरे पास सौ वर्ग नहीं हो सकते हैं जो केवल क्वेरी परिणाम देता है। – Naor

+1

@Nor इसे कम से कम स्थिर बनाते हैं .. – nawfal

उत्तर

23

यदि आप शायद इसे ठीक करने के बाद इसका उपयोग कर रहे हैं, लेकिन यदि आप इसे बहुत कुछ करेंगे तो आपको कुछ और सामान्य सामान करने की कोशिश करनी चाहिए। मैंने DataTable के लिए एक एक्सटेंशन विधि लिखने के बारे में एक ब्लॉग पोस्ट लिखा है जो ऑब्जेक्ट्स की एक सूची बनाता है। यह प्रथा के अनुसार काम करता है उस वस्तु में गुण एक ही नाम होना चाहिए के रूप में जमा की प्रक्रिया में कॉलम (मैं संग्रहीत प्रक्रिया में नाम बदल जाएगा अगर मैं कर सकता):

public static class DataTableExtensions 
{ 
    public static IList<T> ToList<T>(this DataTable table) where T : new() 
    { 
     IList<PropertyInfo> properties = typeof(T).GetProperties().ToList(); 
     IList<T> result = new List<T>(); 

     foreach (var row in table.Rows) 
     { 
      var item = CreateItemFromRow<T>((DataRow)row, properties); 
      result.Add(item); 
     } 

     return result; 
    } 

    public static IList<T> ToList<T>(this DataTable table, Dictionary<string, string> mappings) where T : new() 
    { 
     IList<PropertyInfo> properties = typeof(T).GetProperties().ToList(); 
     IList<T> result = new List<T>(); 

     foreach (var row in table.Rows) 
     { 
      var item = CreateItemFromRow<T>((DataRow)row, properties, mappings); 
      result.Add(item); 
     } 

     return result; 
    } 

    private static T CreateItemFromRow<T>(DataRow row, IList<PropertyInfo> properties) where T : new() 
    { 
     T item = new T(); 
     foreach (var property in properties) 
     { 
      property.SetValue(item, row[property.Name], null); 
     } 
     return item; 
    } 

    private static T CreateItemFromRow<T>(DataRow row, IList<PropertyInfo> properties, Dictionary<string, string> mappings) where T : new() 
    { 
     T item = new T(); 
     foreach (var property in properties) 
     { 
      if(mappings.ContainsKey(property.Name)) 
       property.SetValue(item, row[mappings[property.Name]], null); 
     } 
     return item; 
    } 
} 

अब आप कॉल कर सकते हैं

var items = dt.ToList<Item>(); 

या

var mappings = new Dictionary<string,string>(); 
mappings.Add("ItemId", "item_id"); 
mappings.Add("ItemName ", "item_name"); 
mappings.Add("Price ", "price); 
var items = dt.ToList<Item>(mappings); 

ब्लॉग पोस्ट यहाँ है: http://blog.tomasjansson.com/2010/11/convert-datatable-to-generic-list-extension

ऐसे कई तरीके हैं जिसमें आप इस विस्तार कर सकते हैं कर रहे हैं, तो आप विस्तार बता कैसे इस तरह नाम से मेल करने की जरूरत नहीं है में स्तंभों को मैप करने, मानचित्रण शब्दकोश किसी तरह शामिल हो सकते हैं। या आप मैपिंग में उन संपत्ति नामों की एक सूची जोड़ सकते हैं जिन्हें आप बाहर करना चाहते हैं।

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

अपडेट 2: मैंने मैपिंग्स डिक्शनरी के साथ हिस्सा जोड़ा लेकिन मैंने इसे स्वयं नहीं किया है, इसलिए यह संकलित नहीं हो सकता है। हालांकि, अवधारणा वहां है और मुझे लगता है कि यह काम करता है।

+0

अच्छा जवाब। पुन: प्रयोज्यता + –

+0

धन्यवाद ... मैं इसे सरल रखने की कोशिश कर रहा था, और संग्रहीत प्रक्रिया में कॉलम के विरुद्ध अपने ऑब्जेक्ट गुणों से मिलान करना मुश्किल नहीं है :)। –

+1

यहां आप मानते हैं कि डीबी फ़ील्ड के नाम सदस्यों के नामों के बराबर हैं। हमेशा सच नहीं है। क्या मै गलत हु? – Naor

5

सुंदर अच्छा है, लेकिन मैं कुछ सुझाव हैं:

  • बातें वापस एक और प्रकार में पार्स होने के लिए toString डाली है। यह अपने डेटा प्रकार की गड़बड़ी पैदा कर सकते हैं, और धीमी गति से/अक्षम है।

  • अपेक्षा और बातिल की एसक्यूएल सर्वर से आने वाले के लिए जाँच करें।

तो, बजाय:

ItemId = long.Parse(row[_ItemIdDataName].ToString()); 

प्रयास करें:

ItemId = row.Field<long?>(_ItemIdDataName) ?? value_if_null; 

(System.Data के लिए एक संदर्भ जोड़ें।DatasetExtensions फील्ड विस्तार पाने के लिए)

0

आपकी निजी मद निर्माता और load() कार्यों नहीं है अपने Item कक्षा में संबंध रखते हैं।

आप जानते हैं, एक वर्ग को एक चीज और एक चीज अच्छी तरह से करनी चाहिए।

तो कहते हैं कि एक के लिए के लिए बाहर निजी c'tor
1. refactor कोशिश एक सहायक वर्ग कि बस DataRow पार्स करके मद
2. का एक उदाहरण देता है और एक अलग वर्ग है कि बस का उपयोग करता है में load() refactor उपरोक्त सहायक विधि और आइटम ऑब्जेक्ट उदाहरणों की एक सरणी

+0

इस तरह से मुझे कई कक्षाएं मिलेंगी। यदि कोई कनेक्शन है तो मैं चीजों को एकसाथ रखना चाहता हूं। मैं वर्गों के नाम से बाहर भाग गया .. – Naor

+0

@ नॉर: मैं सिर्फ आपके मुख्य प्रश्नों का उत्तर दे रहा हूं;) – Sung

2

AutoMapper के लिए बिल्कुल सही नौकरी देता है।

दो उदाहरण:

http://house9.blogspot.com/2010/11/automapper-datatable-to-list.html

http://www.geekytidbits.com/automapper-with-datatables/

+0

दोस्त! 2 साल!! – Naor

+2

@ नॉर वास्तव में - लेकिन ऑटोमैपर अस्तित्व के बाद यह अच्छी तरह से पूछा गया था, और यह अभी भी Google खोजों में एक उत्तर की तलाश में आता है। StackOverflow सर्वोत्तम उत्तरों को खोजने के लिए है, वार्तालाप अच्छी तरह से संबंधों को सुनिश्चित करने के लिए नहीं है और फिर बंद कर दिया गया है - यदि आप यही चाहते हैं, तो Google समूह का उपयोग करें। –

+0

यह उत्तर "उत्तर" के रूप में चिह्नित किया जाना चाहिए –

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