2013-07-05 151 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