开发者

WCF Data Services + LINQ Projection into a custom type

I'm trying to project parts of a Display and its list of locations from a WCF Data service into a custom type. Is this doable in WCF Data Services in a Silverlight client? There is some help here, but it doesn't show getting a list back as well as simple strings.

Currently I'm getting "NotSupportedException: Constructing or initializing instances of the type UserQuery+Info with the expression d.Base.Title is not supported.". It would be a bonus if you could tell me how to do Expand on Locations in this syntax (I know about Displays.Expand("Locations")) or if I need 开发者_StackOverflow中文版it.

LINQPad snippet

var displays = from d in Displays.Where(d => d.Id == 3136)
select new Info
{
Name = d.Base.Title,

};


displays.Dump();

}
public class Info
{
private string name;
public string Name
{
  get
    {
      return this.name;
    }

    set
    {
      this.name = value;
    }
}
public IEnumerable<Location> locations;
public IEnumerable<Location> Locations
{
get{ return this.locations;}
set{ this.locations = value;}
}


The problem is that you are effectively asking your WCF server to construct some type it has no knowledge about. Since it is unable to do so, you have to it yourself on your computer:

Displays
  .Where(d => d.Id == 3136)
  .AsEnumerable()
  .Select(d => new Info { Name = d.Base.Title })

This will run the Where() on the server, but the Select() on your computer.


As already noted by svick you can't ask the server for types it doesn't understand (at least not using OData that is). But you can still only ask for properties you want and nothing more.

Since I don't have your service available the below sample uses the demo service on odata.org:

    DemoService ctx = new DemoService(new Uri("http://services.odata.org/OData/OData.svc/"));

    var q =
        ctx.Products
            .Where(p => p.ID == 1)
            .Select(p =>
                new Product
                {
                    Category = new Category
                    {
                        Name = p.Category.Name
                    }
                });

    var r =
        q.AsEnumerable()
            .Select(p =>
                new
                {
                    CategoryName = p.Category.Name
                });

The first query "q" will run compoletely on server (except for creation of the client side objects) and it will only get the Name of the category (and metadata about all the entities in question). It will translate to URL like /Products(1)?$expand=Category&$select=Category/Name.

The second query starts with the AsEnumerable, which effectively executes the first query and then it just performs a simple transform into an anonymous type. This is done completely on the client (no server interaction).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜