LINQ IQueryable anidado y WCF WebApi

I have a method like this that works as expected.

[WebGet]
public IQueryable<BuildJobModel> GetCustomers()
{
    var context = new MyDataContext(); // ADO.NET Entity Data Model
    var query = from c in context.Customers
                select new CustomerModel {
                    Id = c.Id,
                    Name = c.Name
                };
    return query;
}

But when I try to create a more complex query like this, it doesn't work.

[WebGet]
public IQueryable<BuildJobModel> GetCustomers()
{
    var context = new MyDataContext(); // ADO.NET Entity Data Model
    var query = from c in context.Customers
                select new CustomerModel {
                    CustomerId = c.CustomerId,
                    Name = c.Name,
                    Orders = from o in c.Orders
                             select new OrderModel {
                                 OrderId = o.OrderId,
                                 Details = o.Details
                             }
                };
    return query;
}

The Models look like this:

public class CustomerModel
{
    public int CustomerId { get; set; }
    public string Name { get; set; }
    public IEnumerable<OrderModel> Orders { get; set; }
}

public class OrderModel
{
    public int OrderId { get; set; }
    public string Details { get; set; }
}

La excepción:

Cannot serialize member Proj.CustomerModel.Logs of type System.Collections.Generic.IEnumerable`1[[Proj.OrderModel, Proj, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] because it is an interface.

My Goals:

  • I want to be able to expose an IQueryable interface.
  • I want to return nested data.
  • I want to use my own Models, not the ado.net entities
  • I want to hit the database with as few queries as possible (one would be best).

preguntado el 01 de febrero de 12 a las 01:02

3 Respuestas

Lo recomiendo encarecidamente no exposición IQueryable as a return type of a WCF service.

  • WCF was designed to return data not queries
  • You lose control over the nature of the query: someone might potentially use this query in a way that is resource-intensive

Ideally, if you want to return collections use array or a generic list.

With respect to your list of goals:

  1. Can you explain this? I don't see what IQueryable interface has to do with nested data.
  2. You can still return arrays or lists of tu modelos
  3. You have better control over performance if you execute query locally and return results instead

Actualizar: Echa un vistazo a Servicios de datos WCF - that might be able to do what you want.

Respondido 01 Feb 12, 05:02

that issue was brough up, though the web service is used internally and exclusively by one project so we went that route. - joelnet

Returning list of results (instead of IQueryable) does not prevent you from having nested data. All you do is pre-populate any nested data you want to return. - Arnold Zokas

IQueryable isn't messed with in WCF. It's not like normal c# code - Darren Kopp

IQueryable in WCF Web API (!= classic WCF) is used for OData like querying. - Alexander Zeitler

I want to use IQueryable so SQL query will be generated based off the request. I also want to return nested data, because that is the dataset I need. - joelnet

In case you're trying to return JSON: the build in JsonFormatter is not able to (de)serialize interfaces. You should try the JSON.NET Formatter from WebApiContrib.

Respondido 01 Feb 12, 11:02

I think you just need to use an array rather than IEnumerable, like so...

public class CustomerModel
{
    public int CustomerId { get; set; }
    public string Name { get; set; }
    public OrderModel[] Orders { get; set; }
}

public class OrderModel
{
    public int OrderId { get; set; }
    public string Details { get; set; }
}

If you're serializing this to json/xml I suspect the built-in serializers don't know what to do with IEnumerable.

Respondido 02 Feb 12, 03:02

You have to use IEnumerable with LINQ to Entities. You can't use an Array. - joelnet

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.