Sql – How to query Anonymous Type collection

anonymous-typeslinqlinq-to-sql

How do you query a collection which is populated/created with select new?

I have this BindingSource:

this.bindingSource.DataSource = 
    from row in db.Table
    select new 
    {
      name = row.Name + row.Num.ToString()
    };

I'd like to query it like I do with other BindingSources:

var query = from row in (IEnumerable<Table>)anotherBindingSource.List
            where row.name == "asd"
            select row;

Since bindingSource contains anonymous types I get this error:

Unable to cast object of type
'System.Data.Linq.SortableBindingList1[<>f__AnonymousType815
etc. etc. to type 'System.Collections.Generic.IEnumerable`1[Table]'.

What should I do?

Best Answer

Well, not sure exactly what you're trying to do here, but an anonymous type != a Table object. The exception indicates you're trying to cast an IEnum of an anonymous type (a compiler-generated class with a weird name) to an IEnum of type Table.

You can't cast types willy nilly in C#. You can't, for instance, do this:
(Table)"Lol I'd like to be a table pls kthx"
You can't cast any type that isn't already a Table, or extends from Table, to a Table.

So what you're asking is impossible. You should probably take a step back and ask a more general question about what you're trying to accomplish.


Some more on anon types... They only really have meaning within the scope of the method in which they are defined. It appears you might be returning your anon type enumeration from a method call and then are attempting to sort. This won't work, as once the anonymous type leaves the method scope it is considered (at least by intellisense) to be an object and the only way to get at its properties is to use reflection.

If your example isn't just a simplified version, you could just skip the anon type altogether...

this.bindingSource.DataSource = 
    from row in db.Table
    select row.Name + row.Num.ToString();

This is an IEnumerable, and can be queried thusly:

var query = from row in anotherBindingSource
            where row.StartsWith("asd")
            select row;

However it doesn't look like you're accomplishing much at all with this...


You cannot query anonymous types outside of the scope in which they are defined.

This works:

public void Worthless(Hurr hurr)
{
  var query = from x in hurr select new { x.Durr };

  var requery = from x in query where x.Durr == "lol" select x;
}

This does not:

public class Anonymous
{
  public IEnumerable GetMyDurrs(Hurr hurr)
  {
    return from x in Hurr select new { x.Durr };
  }

  public IEnumerable WeedMyDurrs(Hurr hurr, string value)
  {
    // this won't compile
    return from x in GetMyDurrs(hurr) where x.Durr == value select x;
  }
}

The second example won't compile because the anonymous type was defined within another scope.

The only way to get this to work is to define a type.

public class Anonymous
{
  public IEnumerable<Anonymous.MyDurr> GetMyDurrs(Hurr hurr)
  {
    return from x in Hurr select new MyDurr { Durr = x.Durr };
  }

  public IEnumerable<Anonymous.MyDurr> WeedMyDurrs(Hurr hurr, string value)
  {
    // this won't compile
    return from x in GetMyDurrs(hurr) where x.Durr == value select x;
  }

  public class MyDurr { public string Durr {get;set;} }
}