Michael
Michael

Reputation: 41

Create a Linq statement with intermediate results

I would like to convert the following code to a Linq statement.

                int x, y, z;
                List<POINT> l = new List<POINT>();

                foreach (NODE n in nodesEnumerable)
                {
                    x = n.propNodeNumber;
                    foreach (BOARD b in n.propNodeBoardList)
                    {
                        y = b.propBoardNumber;
                        foreach (DEVICE d in b.propBoardDeviceList)
                        {
                            z = d.propDeviceNumber;
                            if (d.propDeviceInstalled == DEVICE_INSTALLED_Types.Enabled)
                            {
                                POINT p = new POINT();
                                p.propPointNodeNumber = x;
                                p.propPointSlotNumber = y;
                                p.propPointAddressNumber = z;
                                p.propObjectDevice = d;

                                l.Add(p);
                            }
                        }
                    }
                }

                foreach (POINT pp in l)
                {
                    Console.WriteLine(pp.propObjectDevice.ToString());
                }

I created the Linq statement below to implement the code above and it partially works in that I'm able to store 2 of the 4 parameters in the POINT object. The commented lines are the two fields I can not get a value for.

I need to save some intermediate results during the Linq process which I'm not able to do now.

I also don't understand why n.propDeviceNumber works when I assumed it should have been d.propDeviceNumber.

                list = from n in nodesEnumerable
                .SelectMany(b => b.propNodeBoardList)
                .SelectMany(d => d.propBoardDeviceList)
                       where (n.propDeviceInstalled == DEVICE_INSTALLED_Types.Enabled)
                       select (new POINT()
                       {
                           //propPointNodeNumber = 
                           //propPointSlotNumber = b.propBoardNumber,
                           propPointAddressNumber = n.propDeviceNumber,
                           propObjectDevice = n
                       });

                foreach (POINT p in list)
                {
                    Console.WriteLine(p.propObjectDevice.ToString());
                }

I was able to get the Linq statement to work properly in that I was able to save all the intermediate results necessary to update the POINT in an earlier version of my code when I used a BOARD[] BoardArray instead of LIST<> NodeBoardList and when I used DEVICE[] DeviceArray instead of LIST<> BoardDeviceList. The Linq statement is below.

                list =
                    from n in nodesEnumerable
                    from b in n.BoardArray
                    from d in b.DeviceArray
                    where d.propDeviceInstalled == DEVICE_INSTALLED_Types.Disabled
                    select (new POINT()
                    {
                        propPointNodeNumber = n.propNodeNumber,
                        propPointSlotNumber = b.propBoardNumber,
                        propPointAddressNumber = d.propDeviceNumber,
                        propObjectDevice = d
                    });

                foreach (var p in list)
                {
                    Console.WriteLine(p.ToString());
                } 

When I used the Arrays I was able to get the Linq statement to work but I've converted all of my code to use Lists and now I can't get the Linq statement to work properly. Using Lists in my code works so much better in all the other aspects of the program except getting this Linq statement to work.

I really want to use the Linq statements instead of hardcoding this functionality since I have a number of similar Linq statements I must create.

Thanks for any suggestions.

Upvotes: 0

Views: 641

Answers (1)

Dragos Bobolea
Dragos Bobolea

Reputation: 782

Both List and Array are IQueriable, so there's no difference as far as LINQ goes. The problem lies in your SelectMany() method. I don't understand why you'd write it like that, when the LINQ in your last snippet was good.

Of course you cannot use b and n for the 2 properties in your second snippet, because they are from some previous lambda expressions, they have nothing to do with your LINQ query under there.

I've put up some dummy classes, and successfully compiled the linq (which is almost exactly your query)

        var nodes = new List<NODE>();
        var linq = from n in nodes
                   from b in n.propNodeBoardList
                   from d in b.propBoardDeviceList
                   where d.propDeviceInstalled == 1
                   select new POINT() 
                   {
                    propPointNodeNumber = n.propNodeNumber,
                    propPointSlotNumber = b.propBoardNumber,
                    propPointAddressNumber = d.propBoardDeviceNumber,
                    propObjectDevice = d
                   };

Edit: for further clarification, when you wrote

from n in nodesEnumerable
                .SelectMany(b => b.propNodeBoardList)
                .SelectMany(d => d.propBoardDeviceList)

considering the methods have "higher precedence" so-to-speak than LINQ, what actually happens is:

  1. nodesEnumerable.SelectMany(b => b.propNodeBoardList) returns a flattened List<BOARD> from all the nodes, let's call it bList
  2. bList.SelectMany(d => d.propBoardDeviceList) returns a flattened device list from all the boards returned by the previous function
  3. the actual collection that n is getting values from is the device list from 2., so n is actually a DEVICE. You can hover your mouse cursor over it for IntelliSense to confirm this fact. Hope that clears it up

Upvotes: 1

Related Questions