2015-03-13 51 views
2

我有一個如下所示的DataSet。使用LINQ在兩個表之間選擇不同的值

DataSet

我所試圖做的是填充的對象與儘可能多的信息可用。

所以我想從頂級數據集中獲取UnitNum 65002,其餘的從單列表中獲取。

我的代碼:

foreach (DataRow row in dsUnits.Tables[0].Rows) 
    { 
     var unit = new Unit.Unit 
     { 
      UnitNum = row["UnitNumber"].NullSafeToString(), 
      CustCode = row["CustCode"].NullSafeToString(), 
      Year = row["Year"].NullSafeToString(), 
      Make = row["Make"].NullSafeToString(), 
      Model = row["Model"].NullSafeToString() 
     }; 

     UnitsInvolvedInBreakdown.Add(unit); 
    } 

    foreach (DataRow row in dsUnits.Tables[1].Rows) 
    { 
     if (UnitsInvolvedInBreakdown.Where(x => x.UnitNum == row["UnitNumber"].ToString()).Count() == 0) 
     { 
      var unit = new Unit.Unit 
      { 
       UnitNum = row["UnitNumber"].ToString() 
      }; 

      UnitsInvolvedInBreakdown.Add(unit); 
     } 
    } 

這似乎真的效率低下給我,我想下面的代碼去沒有結果,

var q = dsUnits.Tables[0].AsEnumerable().Except(dsUnits.Tables[1].AsEnumerable()); 

我的問題基本上是沒有使用LINQ的方式從表格0中選擇UnitNumbers,僅當它們不存在於表格1中時

更好的解釋。

的單元數將在表1中它可能是在表0.1

如果是在表0,我想要得到的信息,從there..i有更多的信息。

如果它不在表0中,我想從表1獲取信息,因爲我必須得到我所能得到的信息。但我不想重複。

+0

這是與實體框架? – 2015-03-13 14:38:41

+0

我想要... – DidIReallyWriteThat 2015-03-13 14:40:17

回答

1

如果我理解你的要求,這是你在找什麼。它首先需要所有的表之一,那麼所有通過不在表中的一個,但在表中的兩個一個LINQ左外連接:

var unitsFrom1 = dsUnits.Tables[0].AsEnumerable() 
    .Select(row => new Unit.Unit 
    { 
     UnitNum = row["UnitNumber"].NullSafeToString(), 
     CustCode = row["CustCode"].NullSafeToString(), 
     Year = row["Year"].NullSafeToString(), 
     Make = row["Make"].NullSafeToString(), 
     Model = row["Model"].NullSafeToString() 
    }); 

var unitsFrom2Notin1 = 
    from row in dsUnits.Tables[1].AsEnumerable() 
    join u1 in unitsFrom1 
    on row.Field<string>("UnitNumber") equals u1.UnitNum into outer 
    from outerJoin in outer.DefaultIfEmpty() 
    where outerJoin == null 
    select new Unit.Unit 
    { 
     UnitNum = row["UnitNumber"].NullSafeToString() 
    }; 

現在你可以Concat的兩個:

IEnumerable<Unit.Unit> result = unitsFrom1.Concat(unitsFrom2Notin1); 

下面是一個不同的方法,更可維護,應該在任何情況下工作。您可以實現自定義IEqualityComparer<Unit>,您可以將其用於許多(基於集合的)LINQ方法,如Join,Intersect,Union,GroupBy。你也可以用它作爲HashSet<Unit.Unit>,我更喜歡這種情況。這裏是一個可能的實現UnitComparer的:

public class UnitComparer : IEqualityComparer<Unit> 
{ 
    public bool Equals(Unit x, Unit y) 
    { 
     if (x == null && y == null) return true; 
     if (x == null || y == null) return false; 

     return x.UnitNum == y.UnitNum; 
    } 

    public int GetHashCode(Unit obj) 
    { 
     return obj == null || obj.UnitNum == null ? 0 : obj.UnitNum.GetHashCode(); 
    } 
} 

這裏是一個簡單的循環,你需要採取一切從第一和所有未從第二第一。注意HashSet<T> constructor,我使用:

var uniqueUnits = new HashSet<Unit.Unit>(new Unit.UnitComparer()); 
foreach (DataRow row in dsUnits.Tables[0].Rows) 
{ 
    Unit.Unit unit = new Unit.Unit 
    { 
     UnitNum = row["UnitNumber"].NullSafeToString(), 
     CustCode = row["CustCode"].NullSafeToString(), 
     Year = row["Year"].NullSafeToString(), 
     Make = row["Make"].NullSafeToString(), 
     Model = row["Model"].NullSafeToString() 
    }; 
    uniqueUnits.Add(unit); 
} 
foreach (DataRow row in dsUnits.Tables[1].Rows) 
{ 
    Unit.Unit unit = new Unit.Unit 
    { 
     UnitNum = row["UnitNumber"].NullSafeToString() 
    }; 
    uniqueUnits.Add(unit); 
} 

HashSet<T>.Add回報false,如果它不能被添加,因爲它已經在集合。

+0

我喜歡它。我在想有一種方法可以使用Intersect功能。謝謝。我將運行一些單元測試來查看哪個更快。 – DidIReallyWriteThat 2015-03-13 14:59:57

+0

@CalvinSmith:我不明白'Intersect'在這裏可以如何幫助。如果您在'Unit.Unit'中重寫了'Equals' +'GetHashCode',則可以使用['Union'](https://msdn.microsoft.com/en-us/library/vstudio/bb341731%28v=vs。 100%29.aspx)。您也可以使用['Union'](https://msdn.microsoft.com/en-us/library/vstudio/bb358407(v = vs.100).aspx)的重載與自定義'IEqualityComparer '重載。 – 2015-03-13 15:03:13

+0

此外,它在concat中生成重複單元65002。我不認爲只是在concat的末尾添加一個明顯的可以修復它,但生病嘗試下一個 – DidIReallyWriteThat 2015-03-13 15:07:42

0

我發現數據集傾向於在我處於linq心境時拋棄我。我發現通過類構建實體更容易,然後使用linq查詢實體。由於時間不夠,我複製了一個MSDN示例。你可以根據你的需要修改它。

var query = 
    from contact in contacts 
    from order in orders 
    where contact.ContactID == order.Contact.ContactID 
     && order.TotalDue < totalDue 
    select new 
    { 
     ContactID = contact.ContactID, 
     LastName = contact.LastName, 
     FirstName = contact.FirstName, 
     OrderID = order.SalesOrderID, 
     Total = order.TotalDue 
    }; 

foreach (var smallOrder in query) 
{ 
    Console.WriteLine("Contact ID: {0} Name: {1}, {2} Order ID: {3} Total Due: ${4} ", 
     smallOrder.ContactID, smallOrder.LastName, smallOrder.FirstName, 
     smallOrder.OrderID, smallOrder.Total); 
} 

}

+0

目前尚不清楚這是如何幫助從表1中全部獲取,並且所有從表2中丟失這是核心問題。樣本完全不相關,不是嗎? – 2015-03-13 15:20:18

+0

這並沒有真正回答這個問題。 – 2015-03-13 15:21:23

+0

我試圖建議,而不是直接從查詢數據集的轉變。是樣本不相關,但給出了一個查詢實體的linq構造。它沒有處理他的查詢應該如何顯示。我將研究這一點 – 2015-03-13 15:39:54