简体   繁体   English

LINQ加入和orderby问题

[英]LINQ join and orderby issues

OK, I've been banging my head against this for a few days, and after studying LINQ I think I am on the right track. 好吧,我已经为此奋斗了几天,研究LINQ之后,我认为我走对了。 But I have a SQL brain and that is sometimes hard to translate to C#. 但是我有一个SQL头脑,有时很难转换为C#。

I have two arrays, one sorted alphabetically, and the other ordered by ID. 我有两个数组,一个按字母顺序排序,另一个按ID排序。 I need to order the second array alphabetically. 我需要按字母顺序排列第二个数组。 The IDs are the joining factor. ID是连接因素。 IEAID = P.ID. IEAID =P.ID。

Here are my arrays and example values; 这是我的数组和示例值;

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}

Edit: updated this to show _assignmentControls contains a sub array. 编辑:更新此内容以显示_assignmentControls包含一个子数组。 I didn't make it so excuse the insanity. 我没有那么疯狂的借口。 It actually contains a copy of _priceLevels... 它实际上包含_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}

Part of the problem as that I'm trying to compare/join an ArrayList and an IGenericListItem. 部分原因是我试图比较/加入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

This Returns me an _assignmentControls table sorted by the values in _priceLevels. 这会给我一个_assignmentControls表,该表按_priceLevels中的值排序。

In C# LINQ I got this far, but can't seem to get it right; 在C#LINQ中,我已经走了很远,但似乎无法正确解决。

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

I am getting red squigglies under join and orderby and the p in p.Name is red. 我在join和orderby下出现红色弯曲,p.Name中的p为红色。 And A) it doesn't work. 和A)它不起作用。 B) I'm not sure it will return sortedList as a sorted version of _assignmentControls sorted by _priceLevels.Name. B)我不确定它将返回sortedList作为按_priceLevels.Name排序的_assignmentControls的排序版本。

EDIT: When I hover over "join" I get "The type arguments for the method 'IEnumerable System.Linq.Enumerable.Join(this Enumerable,IEnumerable, Func,Func....'cannot be infered from the query. I am researching that now. 编辑:当我将鼠标悬停在“联接”上时,我得到“无法从查询中推断方法'IEnumerable System.Linq.Enumerable.Join(此Enumerable,IEnumerable,Func,Func ....'的类型参数。我是现在研究。

Thanks for looking! 感谢您的光临!

When I hover over "join" I get "The type arguments for the method IEnumerable System.Linq.Enumerable.Join(this Enumerable,IEnumerable, Func,Func.... cannot be infered from the query. 当我将鼠标悬停在“ join”上时,我得到“方法IEnumerable System.Linq.Enumerable.Join(this Enumerable,IEnumerable, Func,Func....无法从查询中推断出IEnumerable System.Linq.Enumerable.Join(this Enumerable,IEnumerable, Func,Func....的类型参数。

I can explain what is going on here so that you can track it down. 我可以解释这里发生了什么,以便您可以对其进行跟踪。

When you say 当你说

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

the compiler translates that into: 编译器将其转换为:

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

Enumerable.Join is a generic method that has four type parameters: the element type of the first collection, the element type of the second collection, the key type, and the result type. Enumerable.Join是具有四个类型参数的通用方法:第一个集合的元素类型,第二个集合的元素类型,键类型和结果类型。

If you're getting that error then one of those four things cannot be deduced given the information you've provided to the compiler. 如果遇到该错误,那么根据您提供给编译器的信息,就无法推断出这四件事之一。 For example, maybe: 例如,也许:

  • The type of the first collection is not actually a sequence. 第一个集合的类型实际上不是序列。
  • The type of the second collection is not actually a sequence. 第二个集合的类型实际上不是序列。
  • The type of the result cannot be deduced 无法推断结果的类型
  • The two keys are of inconsistent types and there is no unique best type. 这两个键的类型不一致,并且没有唯一的最佳类型。

That last point is the most likely one. 最后一点是最有可能的。 Suppose for example the first key is int and the second key is short . 例如,假设第一个键为int ,第二个键为short Since every short can be converted to int , int would win, and the second key would be automatically converted to int . 由于每个short都可以转换为int ,因此int将获胜,第二个键将自动转换为int Now suppose that the first key type is Giraffe and the second key type is Tiger . 现在假设第一个键类型是Giraffe ,第二个键类型是Tiger Neither is better than the other. 两者都不比另一个更好。 C# does not say "oh, they're both kinds of Animal , so let's pick that." C#不会说“哦,它们都是Animal ,所以让我们选择它。” Rather, it says that you haven't provided enough information to determine which one you meant; 而是说您没有提供足够的信息来确定您的意思。 you should cast one of them to Animal and then it becomes clear. 您应该将其中之一投给Animal ,然后变得很清楚。

Make sense? 说得通?

There's a half-hour video of me explaining this feature back in 2006 -- this was back when I was adding the feature in question to the compiler -- so if you want a more in-depth explanation, check it out. 我有一个半小时的视频,早在2006年就解释了此功能-这是我将有问题的功能添加到编译器中时的情况-因此,如果您需要更深入的说明,请查看。

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

UPDATE: I just read your question again more carefully: 更新:我只是再次仔细阅读了您的问题:

Part of the problem as that I'm trying to compare/join an ArrayList and an IGenericListItem . 部分原因是我尝试比较/加入ArrayListIGenericListItem

There's the problem. 有问题。 The type of the sequence cannot be determined from an ArrayList . 无法从ArrayList确定序列的类型。 You should not use ArrayList anymore. 您不应再使用ArrayList In fact, you should not use it in any code written after 2005. Use List<T> for some suitable T. 实际上,您不应在2005年之后编写的任何代码中使用它。对于某些合适的T,请使用List<T>

Your select clause is wrong, it should be like this: 您的select子句是错误的,应该是这样的:

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

Another issue is that _assignmentControls is of type ArrayList , which has elements of type Object , so the compiler doesn't know the actual type of a , and can't use it as the join criteria since a doesn't have the same type as p.ID . 另一个问题是, _assignmentControls的类型是ArrayList ,其中有一个类型的元素Object ,所以编译器不知道实际类型的a ,既然不能用它作为连接标准a不具有类型相同p.ID

You should use a List<int> (assuming p.ID is of type int ) instead of ArrayList . 您应该使用List<int> (假设p.IDint类型)而不是ArrayList Another option is to specify the type of a explicitly: 另一个选项是指定的类型, a明确的:

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

I think you should write: 我想你应该写:

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

When you write from a in _assignmentControls - you are declaring a variable that refers to current element in a sequance that the operation to be performed on. 当您从_assignmentControls中的a编写时,您正在声明一个变量,该变量以要对其执行操作的顺序引用当前元素。 And when you're calling select - you're projecting element from the sequence. 当调用select时,您将从序列中投影元素。 Imagine it like conveyer. 想象它像传送带。

Let me give you some example with dump data: 让我给你一些转储数据的例子:

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);
            }
        }

Result: 结果:

another test
test

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM