views:

3974

answers:

6

Possible Duplicate:
LINQ to SQL: Return anonymous type?

I have a standard LINQ to SQL query, which returns the data as an anonymous type (containing about 6 columns of data of various datatypes).

I would like to make this returned object available to other parts of the program, either by returning it to the method-caller, or by assigning it to a property of the object containing the method.

How can I do this given that it is an anonymous type ("var")?

EDIT - Here is the code:

    using (ormDataContext context = new ormDataContext(connStr))
    {
        var electionInfo = from t1 in context.elections
                   join t2 in context.election_status
                   on t1.statusID equals t2.statusID
                   select new { t1, t2 };
    }
+9  A: 

Make the anonymous type into a class...

public class Person
{
    public Person() {
    }

    public String Name { get; set; }
    public DateTime DOB { get; set; }
}


Person p = 
    from person in db.People 
    where person.Id = 1 
    select new Person { 
        Name = person.Name,
        DOB = person.DateOfBirth
    }
Chalkey
+1 i just posted an answer just like this, beat me to it. :)
Stan R.
hate it when that happens! :)
Chalkey
OK, so you're basically saying to not use the anonymous class...I agree that this seems a lot clearer. I guess I'm wondering why most of the LINQ samples use var if they are so difficult to work with...
alchemical
@NagaMensch - you can still use the var keyword without creating anonymous types. In the example above, it would be "var p = from person ... select new Person { ... }" and you'd still end up with a Person object instead of an anonymous type
Scott Ivey
@NagaMensch - var is useful when you can't explicitly name the type. If you query a database table for example and only return two columns (imagine LINQToSQL here), var is useful if you dont have/want to create a type for the results - the compiler will do that for you. I'm not saying dont use them, just that var wouldnt work in your current situation.
Chalkey
Would it need to be a List<> of the Person objects? (assuming the data is more than one row)
alchemical
Erm you would have to do List<Person> p = (query here).ToList();
Chalkey
+4  A: 

You cannot type any method in C# to be the explicit type of an anonymous types. They cannot be "named" so to speak and hence cannot appear in metadata signatures.

If you really want to return a value which is an anonymous type there are 2 options

  1. Have the return type of the method be System.Object. You can then do evil casting hacks to get a typed value in another method. This is very fragile and I don't recommend it.
  2. Use a generic method and a type inference trick to get the return type correct. This would require a very interesting signature definition for your approach.

Anonymous types were not really meant to be passed around in this fashion. At the point you need to pass them around between your functions in this manner, you're better off explicitly defining a type.

JaredPar
+2  A: 

Jon Skeet wrote a blog on how to do this, which is quite rightly titled Horribly Grotty Hack. Just as the title suggests, you really shouldn't be looking for ways to return an anonymous type. Instead, you should be creating a type that can be returned as this is the correct way to implement this feature.

Therefore, I recommend you create a concrete definition of the type to be returned and then populate that in your query for it to be returned.

Jeff Yates
...wistfully remembering the recordset object from classic ASP...it seems like this is a trade-off between code-complexity and performance...for a small program no big deal, but on a larger project with hundreds of db calls, making a custom object for every data-set retrieved, and having to change them if db changes, sounds like a pain and increase in code complexity...
alchemical
And it's then that you should consider whether you are using the right technology for the job you're doing. Don't use a spade when what you need is a hammer.
Jeff Yates
so, how could I just have a "recordset" type object, i.e. that stores all the returned types as objects wrapped in a standard .Net object that I can move around easily?
alchemical
I expect you'd need to consider having a known base class and some kind of key/value pair dictionary.
Jeff Yates
+3  A: 

Using var doesn't make it an anonymous type. Using var just means let this variable be of the type available on the right-hand side of the assignment. It's just short hand. If the thing on the right-hand side is a real class, the variable will be of that type.

For example:

var person = new Person { Name = "bob" };

The person variable is of type Person, even though it used the var keyword.

Anonymous types are created using new { Name = ... }. In this case it's a new, anonymous class. The only thing you can assign it to is a variable defined using var (or object) since there is no existing name to use.

For example:

var person = new { Name = "bob" };

In this case, person is an anonymous type defined at run time.

Generally, as @Chalkey says, if you want to pass the result back to another method, use a named type, not an anonymous one.

If you are forced to use an anonymous type, you'll have to pass it back as an object of type Object, then use reflection to get at it's properties.

tvanfosson
I tried this with my code, but the newly named variable ("Person" in your example), does not sure up in intellisense as a usable return type for the method...
alchemical
You'd need to post the code for your method for me to give you any more advice.
tvanfosson
Thx, I just added the code to the question.
alchemical
@NagaMensch -- I would go the route suggested by @Chalkey and create a separate model/class for the join and not use an anonymous type here.
tvanfosson
A: 

If you have to pass around results in a large app you can use Dictionary. Yes you have some overhead when casting but at least you are reducing you throw away objects.

David Robbins
+1  A: 

It kind of depends on how the calling code is going to use the data.

If you are doing simple data binding, are really don't care about the type (i.e. you don't have to explicitly access properties in your C# code), you can pass the results back as an IEnumberable.

In most databinding cases you are calling properties by name, via magic strings, anyway, so the exact type doesn't matter anyway.

Otherwise, you need to convert the anonymous type to a named type.

Chris Brandsma