2012-03-09 13 views
6

क्या आप कृपया निम्न में से क्या गलत है, इसकी जांच कर सकते हैं।डेटाटेबल यूनियन

मैं इस के मिलन की जरूरत है, लेकिन यह 6 के बजाय रिकॉर्ड 5 रिटर्न (क्योंकि "आमिर" दो बार आता है)

DataTable dt1 = new DataTable(); 
dt1.Columns.Add(new DataColumn("Name")); 
dt1.Rows.Add(dt1.NewRow()["Name"] = "Imran"); 
dt1.Rows.Add(dt1.NewRow()["Name"] = "Amir"); 
dt1.Rows.Add(dt1.NewRow()["Name"] = "Asif"); 

DataTable dt2 = new DataTable(); 
dt2.Columns.Add(new DataColumn("Name")); 
dt2.Rows.Add(dt2.NewRow()["Name"] = "Tandulkar"); 
dt2.Rows.Add(dt2.NewRow()["Name"] = "Amir"); 
dt2.Rows.Add(dt2.NewRow()["Name"] = "Sheqwag"); 

DataTable dtUnion = dt1.AsEnumerable() 
    .Union(dt2.AsEnumerable()).CopyToDataTable<DataRow>(); 

उत्तर

9

समस्या यहाँ Linq पता नहीं है कि यह है कि आप Name की तुलना करना चाहते है। इसके बजाए यह सभी ऑब्जेक्ट प्रकारों के लिए करता है जो यह हैश की तुलना करता है जो दो अलग-अलग उदाहरणों के लिए अलग है।

आपको जो करना है उसे केंद्रीय विधि बताएं कि दो वस्तुओं की तुलना कैसे करें। आप एक कस्टम IEqualityComparer बनाकर ऐसा कर सकते हैं जो दो डेटा पंक्तियों की तुलना करता है जिस तरह से आप चाहते हैं।

यहां एक नमूना दिया गया है:

class CustomComparer : IEqualityComparer<DataRow> 
{ 
    #region IEqualityComparer<DataRow> Members 

    public bool Equals(DataRow x, DataRow y) 
    { 
     return ((string)x["Name"]).Equals((string)y["Name"]); 
    } 

    public int GetHashCode(DataRow obj) 
    { 
     return ((string)obj["Name"]).GetHashCode(); 
    } 

    #endregion 
} 

जब Union बुला आप तो इस comparer का एक उदाहरण में पारित करने के लिए की जरूरत है:

var comparer = new CustomComparer(); 
DataTable dtUnion = dt1.AsEnumerable() 
     .Union(dt2.AsEnumerable(), comparer).CopyToDataTable<DataRow>(); 

अधिक जानकारी के लिए देखें:
http://msdn.microsoft.com/en-us/library/bb358407.aspx

सलाह का शब्द:
लिंकक अनुकूलित डेटा कक्षाओं के साथ सबसे अच्छा है, जो DataRow नहीं है। कक्षा में वास्तविक नाम संपत्ति होना सर्वोत्तम है, केवल तब लिंक वास्तव में चमक सकता है।
यदि आपको गतिशील स्कीमा की लचीलापन की आवश्यकता नहीं है तो आपको DataTable से दूर रहना चाहिए और आपको सटीक रूप से समान वर्गों को लागू करना चाहिए, क्योंकि DataTable बेहद सूजन और धीमी है। अपने DataTables 'स्कीमा ही हैं

3

हैं, तो आप सिर्फ मौजूदा DataRowComparer.Default, इसलिए की तरह इस्तेमाल कर सकते हैं:

DataTable dtUnion = dt1.AsEnumerable().Union(dt2.AsEnumerable()).Distinct(DataRowComparer.Default).CopyToDataTable<DataRow>(); 

और सकल समारोह बहुत आसान है जब आप अधिक है कि 2 टेबल संघ की जरूरत है, उदाहरण:

// Create a table "template" 
DataTable dt = new DataTable(); 
dt.Columns.Add(new DataColumn("Name")); 

// Create a List of DataTables and add 3 identical tables 
List<DataTable> dtList = new List<DataTable>(); 
dtList.AddRange(new List<DataTable>() { dt.Clone(), dt.Clone(), dt.Clone()}); 

// Populate the 3 clones with some data 
dtList[0].Rows.Add("Imran"); 
dtList[0].Rows.Add("Amir"); 
dtList[0].Rows.Add("Asif"); 

dtList[1].Rows.Add("Tandulkar"); 
dtList[1].Rows.Add("Amir"); 
dtList[1].Rows.Add("Sheqwag"); 

dtList[2].Rows.Add("John"); 
dtList[2].Rows.Add("Sheqwag"); 
dtList[2].Rows.Add("Mike"); 

// Union the 3 clones into a single DataTable containing only distinct rows 
DataTable dtUnion = dtList 
        .Select(d => d.Select().AsEnumerable()) 
        .Aggregate((current, next) => current.Union(next)) 
        .Distinct(DataRowComparer.Default) 
        .CopyToDataTable<DataRow>();