2009-03-20 8 views
35

Let T1 और टी 2इनर सी # में DataTables के शामिल होने

T1(CustID, ColX, ColY) 

T2(CustID, ColZ) 

मैं संयुक्त तालिका

TJ (CustID, ColX, ColY, ColZ) 

यह कैसे एक सरल तरीके से सी # कोड में किया जा सकता की जरूरत है निम्नलिखित क्षेत्रों के साथ DataTable रों हैं ? धन्यवाद।

उत्तर

46

यदि आपको LINQ का उपयोग करने की अनुमति है, तो निम्न उदाहरण देखें। यह पूर्णांक कॉलम के साथ दो डेटाटेबल्स बनाता है, उन्हें कुछ रिकॉर्ड के साथ भरता है, LINQ क्वेरी का उपयोग करके उनसे जुड़ता है और उन्हें कंसोल पर आउटपुट करता है।

DataTable dt1 = new DataTable(); 
    dt1.Columns.Add("CustID", typeof(int)); 
    dt1.Columns.Add("ColX", typeof(int)); 
    dt1.Columns.Add("ColY", typeof(int)); 

    DataTable dt2 = new DataTable(); 
    dt2.Columns.Add("CustID", typeof(int)); 
    dt2.Columns.Add("ColZ", typeof(int)); 

    for (int i = 1; i <= 5; i++) 
    { 
     DataRow row = dt1.NewRow(); 
     row["CustID"] = i; 
     row["ColX"] = 10 + i; 
     row["ColY"] = 20 + i; 
     dt1.Rows.Add(row); 

     row = dt2.NewRow(); 
     row["CustID"] = i; 
     row["ColZ"] = 30 + i; 
     dt2.Rows.Add(row); 
    } 

    var results = from table1 in dt1.AsEnumerable() 
       join table2 in dt2.AsEnumerable() on (int)table1["CustID"] equals (int)table2["CustID"] 
       select new 
       { 
        CustID = (int)table1["CustID"], 
        ColX = (int)table1["ColX"], 
        ColY = (int)table1["ColY"], 
        ColZ = (int)table2["ColZ"] 
       }; 
    foreach (var item in results) 
    { 
     Console.WriteLine(String.Format("ID = {0}, ColX = {1}, ColY = {2}, ColZ = {3}", item.CustID, item.ColX, item.ColY, item.ColZ)); 
    } 
    Console.ReadLine(); 

// Output: 
// ID = 1, ColX = 11, ColY = 21, ColZ = 31 
// ID = 2, ColX = 12, ColY = 22, ColZ = 32 
// ID = 3, ColX = 13, ColY = 23, ColZ = 33 
// ID = 4, ColX = 14, ColY = 24, ColZ = 34 
// ID = 5, ColX = 15, ColY = 25, ColZ = 35 
+4

यह अंततः मेरे लिए काम किया, लेकिन मैं इस पर एक घंटे से अधिक खर्च किए, अपवाद "निर्दिष्ट डाली मान्य नहीं" के साथ, मेरे विवेक पर सवाल, जब तक मैं करने के लिए (int) table1 [ "मैदान"] से इसे बदल Convert.ToInt32 (table1 [ "मैदान"])। – CindyH

+1

@ सिंडी, आपकी टिप्पणी के लिए बहुत बहुत धन्यवाद, यह मुझे समय बचाया। मुझे लगता है कि यह System.Data.DataTypes के कारण है, जहां int शामिल नहीं है, लेकिन Int32 है। यहां सभी डेटाटाइप्स की सूची: https://msdn.microsoft.com/en-us/library/system.data.datacolumn.datatype(v=vs.110).aspx – FrenkyB

27

मैं एक समारोह है कि एक गुमनाम प्रकार चयनकर्ता का उपयोग कर स्तंभों को परिभाषित करने की आवश्यकता के बिना तालिकाओं में शामिल हो जाएगा चाहता था, लेकिन एक कठिन समय किसी भी कठिनाई हुई। मैं अपना खुद का बनाने के लिए समाप्त हो गया। जब हो रही यह निश्चित रूप अनुकूल नहीं है, इसलिए ध्यान रखें:

private DataTable JoinDataTables(DataTable t1, DataTable t2, params Func<DataRow, DataRow, bool>[] joinOn) 
{ 
    DataTable result = new DataTable(); 
    foreach (DataColumn col in t1.Columns) 
    { 
     if (result.Columns[col.ColumnName] == null) 
      result.Columns.Add(col.ColumnName, col.DataType); 
    } 
    foreach (DataColumn col in t2.Columns) 
    { 
     if (result.Columns[col.ColumnName] == null) 
      result.Columns.Add(col.ColumnName, col.DataType); 
    } 
    foreach (DataRow row1 in t1.Rows) 
    { 
     var joinRows = t2.AsEnumerable().Where(row2 => 
      { 
       foreach (var parameter in joinOn) 
       { 
        if (!parameter(row1, row2)) return false; 
       } 
       return true; 
      }); 
     foreach (DataRow fromRow in joinRows) 
     { 
      DataRow insertRow = result.NewRow(); 
      foreach (DataColumn col1 in t1.Columns) 
      { 
       insertRow[col1.ColumnName] = row1[col1.ColumnName]; 
      } 
      foreach (DataColumn col2 in t2.Columns) 
      { 
       insertRow[col2.ColumnName] = fromRow[col2.ColumnName]; 
      } 
      result.Rows.Add(insertRow); 
     } 
    } 
    return result; 
} 

तुम ऐसा कैसे उपयोग कर सकते हैं का एक उदाहरण::

var test = JoinDataTables(transactionInfo, transactionItems, 
       (row1, row2) => 
       row1.Field<int>("TransactionID") == row2.Field<int>("TransactionID")); 

एक चेतावनी उम्मीद है कि यह भविष्य है जो इस के लिए खोज करता में किसी को भी मदद मिलेगी 20k से ऊपर की संख्या पंक्तियों के लिए। यदि आप जानते हैं कि एक टेबल दूसरे की तुलना में बड़ी होगी, तो पहले छोटे को और एक बड़ा स्थान डालने का प्रयास करें।

+0

क्या इसे सक्षम करने के लिए इसे संशोधित करने का कोई तरीका है कई "शामिल हों" स्थितियों के बीच एक AND या एक OR ऑपरेटर निर्दिष्ट करें? – Igor

+0

सबसे आसान तरीका कोड को नहीं बदला जाएगा और बस अपनी सभी स्थितियों को स्थिति में शामिल होने के लिए पैक करना होगा। उदाहरण के लिए: 'row1.Field (" आईडी ") == पंक्ति 2। फ़ील्ड (" आईडी ") || row1.Field ("CustId") == row2.Field ("CustId") ' – Bognar

+0

लेकिन, तो आप गतिशील रूप से लॉजिकल ऑपरेटर निर्दिष्ट करने में सक्षम नहीं होंगे। – Igor

5

यह मेरा कोड है। सही नहीं है, लेकिन अच्छा काम कर रहा है। मुझे आशा है कि यह मदद करता है किसी को:

static System.Data.DataTable DtTbl (System.Data.DataTable[] dtToJoin) 
    { 
     System.Data.DataTable dtJoined = new System.Data.DataTable(); 

     foreach (System.Data.DataColumn dc in dtToJoin[0].Columns) 
      dtJoined.Columns.Add(dc.ColumnName); 

     foreach (System.Data.DataTable dt in dtToJoin) 
      foreach (System.Data.DataRow dr1 in dt.Rows) 
      { 
       System.Data.DataRow dr = dtJoined.NewRow(); 
       foreach (System.Data.DataColumn dc in dtToJoin[0].Columns) 
        dr[dc.ColumnName] = dr1[dc.ColumnName]; 

       dtJoined.Rows.Add(dr); 
      } 

     return dtJoined; 
    } 
1

इस समारोह में जाना जाता क्षेत्र में शामिल होने के एक साथ 2 टेबल में शामिल हो जाएगा, लेकिन इस में शामिल होने के क्षेत्र को छोड़कर दोनों टेबल पर एक ही नाम के साथ 2 फ़ील्ड की अनुमति भी नहीं कर सकते, एक साधारण संशोधन को बचाने के लिए होगा एक काउंटर के साथ एक शब्दकोश और बस एक ही नाम filds में संख्या जोड़ें।

public static DataTable JoinDataTable(DataTable dataTable1, DataTable dataTable2, string joinField) 
{ 
    var dt = new DataTable(); 
    var joinTable = from t1 in dataTable1.AsEnumerable() 
          join t2 in dataTable2.AsEnumerable() 
           on t1[joinField] equals t2[joinField] 
          select new { t1, t2 }; 

    foreach (DataColumn col in dataTable1.Columns) 
     dt.Columns.Add(col.ColumnName, typeof(string)); 

    dt.Columns.Remove(joinField); 

    foreach (DataColumn col in dataTable2.Columns) 
     dt.Columns.Add(col.ColumnName, typeof(string)); 

    foreach (var row in joinTable) 
    { 
     var newRow = dt.NewRow(); 
     newRow.ItemArray = row.t1.ItemArray.Union(row.t2.ItemArray).ToArray(); 
     dt.Rows.Add(newRow); 
    } 
    return dt; 
}