2013-07-05 56 views
1

好的,我一直對我的頭撞了幾天,在學習LINQ之後,我想我正走在正確的軌道上。但我有一個SQL大腦,有時很難轉化爲C#。LINQ加入和orderby問題

我有兩個數組,一個按字母順序排序,另一個按ID排序。我需要按字母順序排列第二個數組。 ID是連接因素。 I.E. A.ID = P.ID.

這裏是我的數組和示例值;

private IGenericListItem[] _priceLevels = new IGenericListItem[0]; 
_priceLevels is in the form of {ID, Name} 
{3, A} 
{8, B} 
{4, C} 
{7, D} 
{5, E} 
{9, F} 
{1, G} 

編輯:更新這表明_assignmentControls包含一個子陣列。我沒有讓這個瘋狂的理由變成這樣。它實際上包含_priceLevels的副本...問題的

protected ArrayList _assignmentControls = new ArrayList(); 
_assignmentControls is in the form of {ID, LastPrice, NewPrice, _priceLevels[]} 
{1, 1.00, 2.00, _priceLevels} 
{2, 1.00, 2.00, _priceLevels} 
{3, 1.00, 2.00, _priceLevels} 
{4, 1.00, 2.00, _priceLevels} 

部分作爲我試圖比較/加入一個ArrayList和IGenericListItem。

In SQL I would do something like this; 
SELECT A.* 
FROM _assignmentControls A JOIN _priceLevels P 
    ON A.ID = P.ID 
ORDER BY P.Name 

這將返回我在_priceLevels值進行排序的_assignmentControls表。

在C#LINQ我得到了這麼多,但似乎無法得到正確的;

 var sortedList = 
      from a in _assignmentControls 
      join p in _priceLevels on a equals p.ID 
      orderby p.Name 
      select _assignmentControls; 

我在加入和orderby下得到紅色的小方塊,p.Name中的p是紅色的。 和A)它不起作用。 B)我不確定它將返回sortedList作爲按_priceLevels.Name排序的_assignmentControls的排序版本。編輯:當我把鼠標懸停在「加入」時,我得到了「IEnumerable System.Linq.Enumerable.Join(這個Enumerable,IEnumerable,Func,Func ....」方法的類型參數不能從。!查詢我研究,現在

感謝您尋找

+1

將聯接中的'a'更改爲'a.ID'。 –

+0

@newStackExchangeInstance - 我改爲:在a.ID上的_priceLevels中加入p等於p.ID,現在a.ID中的a也是紅色。這讓我感到困惑,因爲我應該能夠引用ArrayList的那個字段。 – BClaydon

+0

我認爲你需要在末尾選擇 –

回答

6

當我將鼠標懸停在「加入」我知道「的方法IEnumerable System.Linq.Enumerable.Join(this Enumerable,IEnumerable, Func,Func....類型參數不能從查詢infered

我解釋是怎麼回事就在這裏,讓你可以跟蹤下來。

當你說

from firstitem in firstcollection 
join seconditem in secondcollection on firstkey equals secondkey 
select result 

編譯器將其分爲:

Enumerable.Join(
    firstcollection, 
    secondcollection, 
    firstitem=>firstkey, 
    seconditem=>secondkey, 
    (firstitem, seconditem)=>result) 

Enumerable.Join是具有四個類型參數的通用方法:所述第一集合,所述第二集合的元素類型,鍵的類型的單元類型,並且將結果類型。

如果你得到那個錯誤,那麼鑑於你提供給編譯器的信息,那麼這四件事中的一件是無法推斷出來的。例如,可能是:

  • 第一個集合的類型實際上並不是一個序列。
  • 第二個集合的類型實際上並不是一個序列。
  • 無法推導出結果的類型
  • 這兩個鍵的類型不一致,並且沒有唯一的最佳類型。

最後一點是最有可能的一個。假設例如第一個密鑰是int而第二個密鑰是short。由於每個short可以轉換爲int,int會贏,第二個鍵會自動轉換爲int。現在假設第一個密鑰類型是Giraffe,第二個密鑰類型是Tiger。兩者都不如其他。 C#不會說「哦,它們都是Animal的兩種,所以我們選擇它。」相反,它表示你沒有提供足夠的信息來確定你的意思;你應該將其中的一個投射到Animal然後變得清晰。

有意義嗎?

2006年有一個半小時的視頻解釋了這個功能 - 當我將這個功能添加到編譯器時,這又回來了 - 所以如果您想要更深入的解釋,請檢查一下。

http://ericlippert.com/2006/11/17/a-face-made-for-email-part-three/

更新:我剛剛看了一遍你的問題更仔細:這個問題作爲我試圖比較

零件/加入一個ArrayListIGenericListItem

存在問題。序列的類型不能從ArrayList確定。你不應該再使用ArrayList。事實上,你不應該在2005年之後編寫的代碼中使用它。對於某些合適的T使用List<T>

+0

這是一個非常翔實的答案,謝謝。現在我正在努力處理類型,但我會得到它。我想弄清楚如何將我的ArrayList和IGenericListItem強制轉換爲相同的類型。謝謝! – BClaydon

+3

@BClaydon:這兩個序列不需要是同一類型的。它們需要是*通用序列類型*,即'IEnumerable ',但這兩個「東西」可以不同。什麼需要是相同的*鍵選擇器類型*。這樣想一下:如果你有一個客戶名單和一個訂單清單,那麼這兩個清單是不同類型的:客戶和訂單。但是,加入列表的選擇器必須是相同的:例如,一個客戶有一個字段Id,而一個訂單有一個字段CustomerId - 兩個連接鍵的類型必須相同。 –

+0

@BClaydon:你非常歡迎! –

2

我想你應該寫:

var sortedList = 
       from a in _assignmentControls 
       join p in _priceLevels on a.ID equals p.ID 
       orderby p.AnotherValue 
       select a; 

當您從在_assignmentControls寫 - 你宣稱是指當前的變量在要執行的操作中的元素上。當你打電話給select時 - 你是從序列中投射元素的。想象它像傳送帶一樣。

讓我給你一些例子有轉儲數據:

public class SomeCLass 
     { 
      public int ID { get; set; } 
      public string Name { get; set; } 
     } 

     public class AnotherClass 
     { 
      public int ID { get; set; } 
      public int Value { get; set; } 
      public int AnotherValue { get; set; } 
     } 

public void TestMEthod() 
     { 
      List<SomeCLass> _assignmentControls = new List<SomeCLass>() 
       { 
        new SomeCLass() { ID = 1, Name = "test"}, 
        new SomeCLass() { ID = 2, Name = "another test"} 
       }; 
      List<AnotherClass> _priceLevels = new List<AnotherClass>() 
       { 
        new AnotherClass() {ID = 1, AnotherValue = 15, Value = 13}, 
        new AnotherClass() {ID = 2, AnotherValue = 5, Value = 13} 
       }; 


      var sortedList = 
      //here you're declaring variable a that will be like caret when you going through _assignmentControls 
      from a in _assignmentControls 
      join p in _priceLevels on a.ID equals p.ID 
      orderby p.AnotherValue 
      select a; 


      foreach (var someCLass in sortedList) 
      { 
       Console.WriteLine(someCLass.Name); 
      } 
     } 

結果:

another test 
test 
3

select條款是錯誤的,它應該是這樣的:

var sortedList = 
     from a in _assignmentControls 
     join p in _priceLevels on a equals p.ID 
     orderby p.Name 
     select a; 

另一個問題是_assignmentControls的類型是ArrayList,它具有Object類型的元素,因此編譯器不知道a的實際類型,因爲a不具有與p.ID相同的類型,所以不能將其用作聯接條件。

您應該使用List<int>(假設p.ID的類型爲int)而不是ArrayList。另一個選項是指定的a明確的類型:

var sortedList = 
     from int a in _assignmentControls 
     join p in _priceLevels on a equals p.ID 
     orderby p.Name 
     select a; 
+0

你是對的,我把它留了下來,但_assignmentControls確實有對象。它實際上包含_priceLevels的副本,這非常令人討厭。 protected ArrayList _assignmentControls = new ArrayList(); _assignmentControls是的形式{ID,LastPrice,NewPrice,_priceLevels []} {1,1.00,2.00,_priceLevels} {2,1.00,2.00,_priceLevels} {3,1.00,2.00,_priceLevels} 早些時候我試着只使用_assignmentControls並使用_priceLevels的子數組,但無法弄清楚。 _priceLevels也是一個局部變量,我想我使用這個變量。 – BClaydon