Brettski
Brettski

Reputation: 20091

How to return multiple classes as IQueryable<T>

Using Linq I would like to return an object that contains customers and invoices they have.

I understand returning a single type from a method:

public IQueryable<customers> GetCustomers()
{
    return from c in customers
           select c;
}

But I am having trouble figuring out multiple objects:

public IQueryable<???> GetCustomersWithInvoices()
{
    return from c in customers
           from inv in c.invoices
           select new {c, ci}  // or I may specify columns, but rather not.
}

I have a feeling I am approaching this the wrong way. The goal is to call these objects from a controller and pass them up to a view, either direct or using a formViewModel class.

Upvotes: 4

Views: 2845

Answers (3)

Brett Widmeier
Brett Widmeier

Reputation: 1077

If you really want to, you can do this, but it is rather awkward.

public IQueryable<T> GetCustomersWithInvoices(T exampleObject)
{
return from c in customers
from inv in c.invoices
select new {c, ci} // or I may specify columns, but rather not.
}

var exampleObject = new {
Customer c = new Customer(),
Invoice i = new Invoice()
};

var returnedObjectOfAnonymousType = GetCustomersWithInvoices(exampleObject);

In this way, you can take advantage of type inference to get your method to return an anonymous type. You have to use this ugly method of passing in an example object to get it to work. I don't really recommend that you do this, but I believe that this is the only way to do it.

Upvotes: 0

Simon Fox
Simon Fox

Reputation: 10561

In the second case you are creating an annonymous type which has method scope. To pass an annonymous type outside the method boundary you need to change the return type to object. This however defeats the purpose of the annonymous type (as you lose the strong typing it provides) , requiring reflection to get access to the properties and their values for the said type.

If you want to maintain this structure as your return type you should create a class or struct consisting of properties to hold the customer and invoice values.

Upvotes: 2

Jim Counts
Jim Counts

Reputation: 12795

You cannot return an anonymous type from a function, they are strictly "inline" classes. You will need to create a concrete type to hold your members if you want to encapsulate them in a function.

Using a view model, as you mentioned, would be a good place to put them.

Here is a scottgu article about anonymous types. From the conclusion of the article:

Anonymous types are a convenient language feature that enable developers to concisely define inline CLR types within code, without having to explicitly provide a formal class declaration of the type. Although they can be used in lots of scenarios, there are particularly useful when querying and transforming/shaping data with LINQ.

There's some good discussion in the comment thread on that page.

Upvotes: 1

Related Questions