2011-06-09 25 views
5

के साथ DataRow या DataReader से निकालें, मैं केवल एक फ़ंक्शन (या एक बेस फ़ंक्शन) के साथ DataRow और DataReader का उपयोग करते समय डेटाबेस से डेटा निकालने में सक्षम होने के लिए एक समाधान की तलाश में हूं।एक फंक्शन

मेरे समस्या तथ्य यह है कि कभी कभी मैं किसी DataReader की जरूरत है और कभी कभी मैं एक DataTable/DataRow लेकिन फिर आदेश उन वस्तुओं से डेटा निकालने के लिए, क्योंकि वे एक अंतरफलक का हिस्सा नहीं है मैं दो अलग डेटा एक्सेस तरीकों की जरूरत की जरूरत की वजह से उपजी।

मूल रूप से

जब मेरे डेटाबेस संरचना में परिवर्तन, मैं में जाने के लिए और कई कार्यों में निम्नलिखित डेटा पुनर्प्राप्ति कोड लिखने के लिए करना चाहते हैं:

someValue = dr["someValue"] 

यह वही वाक्य रचना है और इस एक ही बात करता है एक फ़ंक्शन चाहते हैं जो उस कार्यक्षमता को साझा करता है चाहे मैं डेटाबेस से डेटा निकालने के लिए डेटा रीडर या डेटाटेबल/डेटारो का उपयोग कर रहा हूं।

उत्तर

5

साथ काम करने के लिए आप DbDataReader आधार वर्ग के माध्यम से डेटा का उपयोग करने DataTable कक्षा में CreateDataReader विधि का उपयोग कर सकते हैं छिपाने के लिए एक एडाप्टर बनाएँ। इसलिए आप कार्यान्वयन को बदल सकते हैं लेकिन मैपिंग रख सकते हैं।

public List<MyType> GetMyTypeCollection(DbDataReader reader) 
{ 
//mapping code here 
} 

बेहतर होगा यदि आप एक ओआरएम में स्थानांतरित कर सकते हैं जहां आपको मैन्युअल रूप से मानचित्रण करने की आवश्यकता नहीं है।

इस माइक्रो ORM Dapper

+0

धन्यवाद यह वही है जो मुझे चाहिए!मुझे नहीं पता था कि विधि मौजूद थी। – Nate32

2

उपयोग this लेख एक datatable के लिए DataReader कन्वर्ट करने के लिए और फिर आप एक datatable

के रूप में दोनों इंटरफेस कर सकते हैं तो आप मूल रूप से इस समारोह है कि हो अपने dataLayer से कहा जाता है जोड़ना होगा:

public DataTable ConvertDataReader(SqlDataReader dr) 
{ 
    SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection); 
    DataTable dtSchema = dr.GetSchemaTable(); 
    DataTable dt = new DataTable(); 

    // You can also use an ArrayList instead of List<> 
    List<DataColumn> listCols = new List<DataColumn>();    
    if(dtSchema != null) 
    { 
    foreach (DataRow drow in dtSchema.Rows) 
    { 
     string columnName = System.Convert.ToString(drow["ColumnName"]); 
     DataColumn column = new DataColumn(columnName, 
           (Type)(drow["DataType"])); 
     column.Unique = (bool)drow["IsUnique"]; 
     column.AllowDBNull = (bool)drow["AllowDBNull"]; 
     column.AutoIncrement = (bool)drow["IsAutoIncrement"]; 
     listCols.Add(column); 
     dt.Columns.Add(column); 
    } 
    } 

    // Read rows from DataReader and populate the DataTable 
    while (dr.Read()) 
    { 
    DataRow dataRow = dt.NewRow(); 
    for(int i = 0; i < listCols.Count; i++) 
    { 
     dataRow[((DataColumn)listCols[i])] = dr[i]; 
    } 
    dt.Rows.Add(dataRow); 
    } 
} 

और फिर आपके फ़ंक्शन में जहां आप डेटाटेबल प्राप्त करते हैं, तो आप एक डेटा रीडर करते हैं, तो पाठक को एक डेटाटेबल लौटने के लिए फ़ंक्शन में पास करें:

DataTable dtFromReader = ConvertDataReader(dr); 
0

DataReader के कार्यान्वयन DataTable/DataRow कोड

1

पर एक नजर डालें तो आप एक इकाई के लिए ऑटो नक्शा एसक्यूएल क्वेरी परिणाम की पंक्ति मतलब है? इस कदर?

public static List<T> ToList<T>(this IDataReader idr, int count) where T : new() 
{ 
    if (idr == null) 
     throw new ArgumentNullException("idr"); 

    if (idr.IsClosed) 
     throw new ArgumentException("IDataReader is closed."); 

    Type businessEntityType = typeof(T); 
    List<T> entitys = new List<T>(); 
    Hashtable hashtable = new Hashtable(); 
    PropertyInfo[] properties = businessEntityType.GetProperties(); 

    int idx = 0; 

    foreach (PropertyInfo info in properties) 
    { 
     hashtable[info.Name.ToUpper()] = info; 
    } 

    while (idr.Read()) 
    { 
     if (count > 0) 
      idx++; 

     T newObject = new T(); 
     for (int index = 0; index < idr.FieldCount; index++) 
     { 
      PropertyInfo info = (PropertyInfo)hashtable[idr.GetName(index).ToUpper()]; 
      if (info != null && info.CanWrite) 
      { 
       try 
       { 
        info.SetValue(newObject, idr.GetValue(index), null); 
       } 
       catch 
       { 

       } 
      } 
     } 

     entitys.Add(newObject); 

     if (idx > count) 
      break; 
    } 
    return entitys; 
} 
+0

डीबी कार्यों की लागत है। इसमें प्रतिबिंब जोड़ें, यह काफी धीमा होने जा रहा है। आपको प्रतिबिंब के बजाय अभिव्यक्ति पेड़ों पर भरोसा करना चाहिए। उदाहरण के लिए http://stackoverflow.com/a/19845980/661933 इस उत्तर को देखें और जेनेरिक का उपयोग करें (हैशटेबल के बजाय शब्दकोश का उपयोग करें) – nawfal

0

वैकल्पिक समाधान के रूप में मैंने एक निजी फ़ंक्शन का उपयोग किया जो गतिशील तर्क लेता था। फिर दो सार्वजनिक फ़ंक्शंस जोड़े जो "DataRow" और "DataReader" तर्क लेते थे। आप ज्ञात प्रकारों या इंटरफेस पर कॉल को सीमित करने के लिए इसका उपयोग कर सकते हैं।

public MyResults DoStuff(DataRow dr) 
{ 
    return ActualDoStuff(dr); 
} 

public MyResults DoStuff(DataReader dr) //IDataRecord is better if just reading 
{ 
    return ActualDoStuff(dr); 
} 

private MyResults ActualDoStuff(dynamic dr) 
{ 
    var rez = new MyResults(); 
    rez.someValue = dr["someValue"]; 
    return rez; 
} 

हालांकि चेतावनी का एक शब्द। आपको अपने लोड कोड को फिर से लिखना पड़ सकता है क्योंकि गतिशील पर स्ट्रिंग के माध्यम से उपयोग की जाने वाली डॉ सामग्री का व्यवहार थोड़ा अलग है। अर्थात।

if(dr["someValue"] == DBNull.Value) 

if(dr["someValue"] is DBNull) 

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

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