2013-10-22 124 views
2

我有兩個表:LINQ的更新和合並兩個結果集(從數據表)

Customer:     
+------------------------------+ 
| ID  | Address  | 
|------------------------------| 
| 1   | London, UK  | 
| 2   | Paris, France | 
+------------------------------+ 

Updated Customer:     
+------------------------------+ 
| ID  | Address  | 
|------------------------------| 
| 1   | Birmingham, UK | 
+------------------------------+ 

如何合併表,得到這樣的結果? :

Customer:     
+------------------------------+ 
| ID  | Address  | 
|------------------------------| 
| 1   | Birmingham, UK | 
| 2   | Paris, France | 
+------------------------------+ 

C#/ LINQ的代碼,我試圖與工會:

DataTable customer = new DataTable(); 
customer.Columns.Add("ID", typeof(int)); 
customer.Columns.Add("Address", typeof(string)); 

DataTable updatedCustomer = new DataTable(); 
updatedCustomer.Columns.Add("ID", typeof(int)); 
updatedCustomer.Columns.Add("Address", typeof(string)); 

customer.Rows.Add(1, "London, UK"); 
customer.Rows.Add(2, "Paris, France"); 

updatedCustomer.Rows.Add(1, "Birmingham, UK"); 

var cust = from row in customer.AsEnumerable() 
select new 
{ 
    ID = row[0], 
    Address = row[1] 
}; 

var uCust = from row in updatedCustomer.AsEnumerable() 
select new 
{ 
    ID = row[0], 
    Address = row[1] 
}; 

var updatedTable = cust.Union(uCust); 
//Please use cust and uCust objects, not customer and UpdatedCustomer. 

聯盟給了我一個表與所有3行,但是。

+1

'datatable.Merge'? –

回答

1
var query=from c in customer.AsEnumerable() 
     join uc in updatedCustomer.AsEnumerable() 
     on c.Field<int>("ID") equals uc.Field<int>("ID") into lf 
     from uc in lf.DefaultIfEmpty() 
     select new 
     { 
      ID=c.Field<int>("ID"), 
      Address=uc==null?c.Field<string>("Address"):uc.Field<string>("Address") 
     }; 

//this will get the result you want,but it is not DataTable. 
//you need to convert query to datatable . 
DataTable result =customer.Clone(); 

query.ToList().ForEach(q=>result.Rows.Add(q.ID,q.Address)); 
2

添加一個主鍵,並使用合併將讓你的答案。

DataTable customer = new DataTable(); 
    var customerIdColumn = new DataColumn("ID", typeof(int)); 
    customer.Columns.Add(customerIdColumn); 
    customer.Columns.Add("Address", typeof(string)); 
    customer.PrimaryKey = new[] { customerIdColumn }; 

    DataTable updatedCustomer = new DataTable(); 
    var updatedCustomerIdColumn = new DataColumn("ID", typeof(int)); 
    updatedCustomer.Columns.Add(updatedCustomerIdColumn); 
    updatedCustomer.Columns.Add("Address", typeof(string)); 
    updatedCustomer.PrimaryKey = new[] { updatedCustomerIdColumn }; 

    customer.Rows.Add(1, "London, UK"); 
    customer.Rows.Add(2, "Paris, France"); 

    updatedCustomer.Rows.Add(1, "Birmingham, UK"); 


    customer.Merge(updatedCustomer, false); 

編輯

要使用LINQ做到這一點,你需要一個沒有。我做了這個相當冗長的清晰度。然而,你應該能夠使代碼更加簡潔。

var cust = customer.AsEnumerable(); 
var uCust = updatedCustomer.AsEnumerable(); 

var newCust = (from c in cust join u in uCust on c.Field<int>("ID") equals u.Field<int>("ID") select u); 
var newUCust = 
    (from cu in cust where !(from ucu in uCust select ucu.Field<int>("ID")).Contains(cu.Field<int>("ID")) select cu); 
var joined = newCust.Concat(newUCust); 
+0

有沒有辦法與linq做到這一點呢?我已經將數據錶轉換爲可以枚舉的行,並且迄今爲止對它進行了許多linq操作。 – David

+0

是的,只是一會兒。 – paqogomez

+0

@大衛檢查我編輯的答案,這應該適合你。 – paqogomez

3

您可以編寫自己的比較器,只是比較ID

public class IDComparer : IEqualityComparer<DataRow> 
{ 
    public bool Equals(DataRow x, DataRow y) 
    {   
     return (int) x["ID"] == (int) y["ID"] ; 
    } 

    public int GetHashCode(DataRow obj) 
    {       
     return (int) obj["ID"] ; 
    }    
}   

然後使用它,

var updatedTable = uCust.Union(cust, new IDComparer()) 
+0

非常棒的解決方案 – paqogomez