Link to home
Start Free TrialLog in
Avatar of Mike Eghtebas
Mike EghtebasFlag for United States of America

asked on

Cannot order by type '<>f__AnonymousType0`1[System.String]'. c# LINQ

In the following code, I get Cannot order by type '<>f__AnonymousType0`1[System.String]'. at line 5 at foreach.

Question 1: How can I correct this?

       dynamic outputs = (from output in wscgsContext.Searches
                         group output by new { Key = output.City } into cityGroup
                           select cityGroup.Key).Distinct();//.OrderBy(c => c);

        foreach (String output in outputs)
        {
            cmbCity.Items.Add(output);
        }

Open in new window


And, with .OrderBy(c => c); included, I get:
Cannot convert type '<>f__AnonymousType0<string>' to 'string' at foreach (String output in outputs)

Question 2: How can make it work with distinct?
Avatar of Valliappan AN
Valliappan AN
Flag of India image

As i understand when you put the keyword new , you create anonymous type, can you try without the new casting.
Avatar of Fernando Soto
The dynamic type is causing the issue. try it like this.

dynamic outputs = (from output in wscgsContext.Searches
                   group output by new { Key = output.City } into cityGroup
                   select cityGroup.Key).Distinct().OrderBy(c => c);

foreach (var output in outputs)
{
    cmbCity.Items.Add(output.Key);
}

Open in new window

Avatar of Mike Eghtebas

ASKER

Hi Fernando,

Without OrderBy it works fine:
      dynamic outputs = (from output in wscgsContext.Searches
                           group output by new { Key = output.City } into cityGroup
                           select cityGroup.Key).Distinct();//.OrderBy(c => c);

Open in new window


But with Orderby, I get Cannot order by type '<>f__AnonymousType0`1[System.String]'. at foreach.
Valliappan AN,

I tried, this is what I got:User generated image
Mike, please see my post [Here] I have modified it to work with dynamic type.

I used my original query but made a couple of changes to the for loop.
I had used:

dynamic outputs = (from output in wscgsContext.Searches
                   group output by new { Key = output.City } into cityGroup
                   select cityGroup.Key).Distinct().OrderBy(c => c);

foreach (var output in outputs)
{
    cmbCity.Items.Add(output.Key);
}

Open in new window


Exactly as you had. I am getting error with OrderBy included:  Cannot order by type '<>f__AnonymousType0`1[System.String]'. at foreach.
SOLUTION
Avatar of Fernando Soto
Fernando Soto
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Can you check these please :

dynamic outputs = (from output in wscgsContext.Searches
                   select output.City)
                   .Distinct();

and then,

dynamic outputs = (from output in wscgsContext.Searches
                   select output.City)
                   .Distinct().OrderBy(c => c);

 hth.
Sorry for the delay, brb
Have you tried it this way?
dynamic outputs = (from output in wscgsContext.Searches
                   group output by new { Key = output.City } into cityGroup
                   orderby cityGroup.Key
                   select cityGroup.Key).Distinct();

foreach (var output in outputs)
{
    cmbCity.Items.Add(output.Key);
}

Open in new window


-saige-
Hi -saige-, that is the same exact solution as I gave [here].
Fernando,
The screenshot is attached.  Please let me know what particular nodes you want to see.

Saige,
I used the code it is giving the exact error.

Valliappan AN,
I tired both. There is nor error but also there is no data the combo box.

FYI: My controls, despite their names are listboxes not combo boxes it it makes any difference. I will rename them later as lstCity, etc.
Watch-1.png
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Hi Mike, you used the wrong variable in the Watch window, I like to see output. Thanks.
Mike do you really need to use a dynamic data type for the query seeming it is returning a collection of strings?
Fernando,

I had a vb.net code:
Dim states = From state In customerList Group state By state.State Into stateGroup = Group Select stateGroup.FirstOrDefault().State

Open in new window


I used http://converter.telerik.com/ to convert to c#. I do not know about the other options. Could you please help me with a text of a question I could post so I can get a bit understanding when and why we need to use dynamic as opposed to some other option?

Saige, Your last post works:
       dynamic outputs = (from output in wscgsContext.Searches
                           orderby output.City
                           group output by new { Key = output.City } into cityGroup
                           select cityGroup.Key);

        foreach (var output in outputs)
        {
            cmbCity.Items.Add(output.Key);
        }

Open in new window


Mike
Well he is asking because normally you would do this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EE_Q28562829
{
	class Customer
	{
		public string Name { get; set; }
		public string City { get; set; }
	}

	class Program
	{
		static void Main(string[] args)
		{
			var customers = new List<Customer>() 
			{ 
				new Customer() { City = "St. John", Name = "Carl" },
				new Customer() { City = "Petersburgh", Name = "Peter" },
				new Customer() { City = "Riderstown", Name = "John" },
				new Customer() { City = "Andrews", Name = "Thomas" },
				new Customer() { City = "Riderstown", Name = "Nancy" },
				new Customer() { City = "St. John", Name = "Mindy" },
				new Customer() { City = "Petersburgh", Name = "Daryl" },
				new Customer() { City = "Riderstown", Name = "Ringo" },
				new Customer() { City = "Charlestown", Name = "Mike" },
				new Customer() { City = "St. John", Name = "Nick" },
				new Customer() { City = "Petersburgh", Name = "Bob" },
				new Customer() { City = "Riderstown", Name = "Robert" },
				new Customer() { City = "Andrews", Name = "William" },
				new Customer() { City = "Riderstown", Name = "Billy" },
				new Customer() { City = "St. John", Name = "Denise" },
				new Customer() { City = "Petersburgh", Name = "Michelle" },
				new Customer() { City = "Riderstown", Name = "Terry" },
				new Customer() { City = "Charlestown", Name = "Doris" }
			};

			var outputs = (from output in customers
						orderby output.City
						group output by output.City into cityGroup
						select cityGroup.FirstOrDefault().City);

			foreach (var output in outputs)
				Console.WriteLine(output);

			Console.ReadLine();
		}
	}
}

Open in new window


Produces the same output as above.

-saige-
Try reading this Microsoft documentation and see if it helps. If not let me know.

Using Type dynamic (C# Programming Guide)
For all that, I rely:

 WSCGSoftwareDataContext wscgsContext =  new WSCGSoftwareDataContext(cnn);
Fernando, I really value and appreciate inputs from you, Saige, and the other good experts at EE. Thank you for the link.

Mike
Mike did the solution posted by Saige sort the list in the combo box?
Fernando, Yes, it did. I read the link. Could you possibly rewrite the following without use of dynamic?
dynamic outputs = (from output in wscgsContext.Searches
                           orderby output.City
                           group output by new { Key = output.City } into cityGroup
                           select cityGroup.Key);

        foreach (var output in outputs)
        {
            cmbCity.Items.Add(output.Key);
        }

Open in new window


Would it be like:

Search outputs = (from output in wscgsContext.Searches
This should work.

String[] outputs = (from output in wscgsContext.Searches
                    orderby output.City
                    group output by new { Key = output.City } into cityGroup
                    select cityGroup.Key).ToArray();

cmbCity.Items.AddRange(output);

Open in new window

Mike, my follow-up post rewrites it without using dynamic.

-saige-
Nice use of .addrange fenando.  😃
Fernando, With this code there are 2 errors:

String[] outputs = (from output in wscgsContext.Searches
                    orderby output.City
                    group output by new { Key = output.City } into cityGroup
                    select cityGroup.Key);

        foreach (var output in outputs)
        {
            lstCity.Items.Add(output.Key);
        }

Two complains with String[]:
1. select : Cannot implicitly converr 'System.Ling.IQueryable<Annonymus.Type#>' to 'string[]'.
2. Key: 'string' does not contain a definition for Key (I suppose it needs an extention of some sort)

Saige,

var outputs = (from o...  works fine.

Mike
That is NOT exactly what I posted. I modified the query in a couple of places and got rid of the foreach loop, please re-read the post.
With Aplogy.

I tested the following code. I have 2 problems in bolded areas:

        String[] outputs = (from output in wscgsContext.Searches
                            orderby output.City
                            group output by new { Key = output.City } into cityGroup
                            select cityGroup.Key).ToArray();

        lstCity.Items.AddRange(output);

ToArray(): Extension 'a[ ] IEnumerable<' a>.ToArray<'a>()
                             Anonymous Types:
                             'a is nw { string Key }
                             Creates an array from a System.Collections.Generic.IEnumerable<T>.
                              Coonot imlcitly convert type Anonymous#1[]' to 'string'.

output:  The name output doesn't exist in the current context.
You have to get rid of the anonymous type.  Remove the 'new { Key = output.City }'.  So it would look like:
string[] outputs = (from output in wscgsContext.Searches
		orderby output.City
		group output by output.City into cityGroup
		select cityGroup.FirstOrDefault().City).ToArray();

lstCity.Items.AddRange(outputs);

Open in new window


-saige-
Saige,
Please see the image for the error.User generated image
Well that is simple enough.  This should do the trick:
ListItem[] outputs = (from output in wscgsContext.Searches
		orderby output.City
		group output by output.City into cityGroup
		select new ListItem(cityGroup.FirstOrDefault().City)).ToArray();

lstCity.Items.AddRange(outputs);

Open in new window


-saige-
Saige,

If you get this working, do I owe you another 500 point LOL. All I had for this question are spent. See the result in the attached image. So far I do not owe any point but pretty soon it is going to happen:User generated image
BTW, my control is list box not listview just in case.
Change it to ListItem in both places, I had misread the type in your post.  So it would be like:
ListItem[] outputs = (from output in wscgsContext.Searches
		orderby output.City
		group output by output.City into cityGroup
		select new ListItem(cityGroup.FirstOrDefault().City)).ToArray();

lstCity.Items.AddRange(outputs);

Open in new window


-saige-
It work. But how am I going pay you? Maybe wash your car?
LOL...  It's all good... :)

-saige-