Say I have an OData query that looks like this (My actual query is much more complex):
Orders.Select(z => new { z.SubOrder.Addresses,
z.SubOrder.Cost,
z.SubOrder.SubOrderId,
z.Sequence});
This works fine. Except that the Address object has a sub object on it (StateRef). Since StateRef does a look-up on the State table, it is returned as null.
To illustrate, here is an example of how the address object Address might look:
Address:
string Street 1
string Street 2
StateRef PrimaryState
string City
// ... 42 other string attributes not shown ...
The StateRef
object has the name of the state on it, but also has some other important State properties (maybe state bird?)
So, what I am wondering is, do I have to now create a "sub projection" for z.SubOrder.Addresses that contains all 46 attributes just so that I can access the PrimaryState
item? (I Hope NOT)
Aside from being way more coding, it also means I have to use anonymous types. Which makes my mapping have to be by hand (instead of using AutoMapper).
So what I am looking for is a way to "Expand" the StateRef inside the projection?
Something like this:
Orders.Select(z => new { z.SubOrder.Addresses.Expand("PrimaryState"),
z.SubOrder.Cost, ^
z.SubOrder.SubOrderId, |
z.Sequence}); |
|
// This is not allowed by the compiler ----------+
Trying this give this error:
Invalid anonymous type member declarator. Anonymous type members must be declared with a member assignment, simple name or member access.
Update: Here is an example query to illustrate what I am asking about:
Users.Take(10).Select(x=>new { x.Id, x.Reputation, x.Comments})
Run that against "data.stackexchange.com/stackoverflow/atom". You will see that Comments has a Post object that returns null.
I need that to return the values inside of it.
Note: I know I can manually type all of them out into a "sub" projection. Read above for why I do not want that.
OData expand functionality can be used to query related data. For example, to get the Course data for each Enrollment entity, include ?$ expand=course at the end of the request path: This tutorial uses Postman to test the web API.
The $select option specifies a subset of properties to include in the response body. For example, to get only the name and price of each product, use the following query: Console Copy. GET http://localhost/odata/Products?$select=Price,Name.
The $value option is used to get individual properties of an Entity. There are two ways to get individual properties from an entity. We can get the response in either OData format or get the raw value of the property. We need to add method to the controller named GetProperty here property is a name of the property.
You don't have to create a sub-projection which lists out all 46 attributes, e.g.
(from u in Users
select new
{
u.Id, u.Reputation,Comments = ( from c in u.Comments
select new YourClass {comment = c,
post= c.Post})
}
)
.Take(10)
.....
public Class YourClass
{
public Comment comment {get; set;}
public Post post {get;set;}
}
Not exactly the object graph I imagine you're after.
This aside, one can spend a lot of time trying to write a LinQ expression that will generate the correct OData query, we've found that it is much more time effecient to create your own OData query class with Expand, Filter, Select properties etc. i.e. go straight to writing OData queries instead of trying to craft LinQ queries.
It is certainly possible to do that. For a proof of concept try executing this:
var uri = new Uri( "http://data.stackexchange.com/stackoverflow/atom/Users()?$top=10&$expand=Comments/Post&$select=Id,Reputation,Comments/" );
entities.Execute<User>( uri, "GET", false ).Select( x => new { x.Id, x.Reputation, x.Comments } );
The correct usage of expand is like this:
entities.Users.Expand( "Comments/Post" ).Take( 10 ).ToArray();
I don't know why the writers of the library have decided to disallow using expand with projections, but as the above proof of concept shows, it is certainly possible to do so.
If you don't mind receiving the entire user and making the projection after that, you can go with the second example. Else you can write your own helpers which will produce the URI from the first example, execute them, and add the projection after that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With