-
Notifications
You must be signed in to change notification settings - Fork 352
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for $count in navigation properties #2051
Add support for $count in navigation properties #2051
Conversation
|
||
if (this.lexer.CurrentToken.Text == UriQueryConstants.CountSegment && isSelect) | ||
{ | ||
// $count in only allowed in $expand. e.g $expand=NavProperty/$count |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is
src/Microsoft.OData.Core/UriParser/Parsers/SelectExpandTermParser.cs
Outdated
Show resolved
Hide resolved
/// <summary> | ||
/// This represents one level of expansion for a particular expansion tree. | ||
/// </summary> | ||
public sealed class ExpandedCountSelectItem : ExpandedReferenceSelectItem |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think it's better to derive from ExpandedReferenceSelectItem?
Or shall we have a base NavigationSelectItem, and others derived from it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The semantics are the same though.
Also, ExpandedNavigationSelectItem
inherits from the ExpandedReferenceSelectItem
/// <param name="filterOption">A filter clause for this expand (can be null)</param> | ||
/// <param name="searchOption">A search clause for this expand (can be null)</param> | ||
/// <exception cref="System.ArgumentNullException">Throws if input pathToNavigationProperty is null.</exception> | ||
public ExpandedCountSelectItem(ODataExpandPath pathToNavigationProperty, IEdmNavigationSource navigationSource, FilterClause filterOption, SearchClause searchOption) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only $filter and $search are allowed within nav/$count?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes: From the protocol http://docs.oasis-open.org/odata/odata/v4.01/cs01/part1-protocol/odata-v4.01-cs01-part1-protocol.html#sec_RequestingtheNumberofItemsinaCollect
On success, the response body MUST contain the exact count of items matching the request after applying any $filter or $search system query options, formatted as a simple primitive integer value with media type text/plain. Clients SHOULD NOT combine the system query options $top, $skip, $orderby, $expand, and $format with the path suffix /$count. The result of such a request is undefined.
Looks good to me. |
@KenitoInc I cloned your branch and performed some tests based on the sample scenarios you provided in the PR description.
Result: {
"@odata.context": "http://service/$metadata#Categories(Products())",
"value": [
{
"Id": "PG1",
"Name": "Food",
"Products": [
{
"Id": "P1",
"CategoryId": "PG1",
"Name": "Sugar",
"Color": "White",
"TaxRate": 0.06
},
{
"Id": "P2",
"CategoryId": "PG1",
"Name": "Coffee",
"Color": "Brown",
"TaxRate": 0.06
}
]
},
{
"Id": "PG2",
"Name": "Non-Food",
"Products": [
{
"Id": "P3",
"CategoryId": "PG2",
"Name": "Paper",
"Color": "White",
"TaxRate": 0.14
},
{
"Id": "P4",
"CategoryId": "PG2",
"Name": "Pencil",
"Color": "Black",
"TaxRate": 0.14
}
]
}
]
} Test 1:
Result: {
"@odata.context": "http://service/$metadata#Categories(Products/$ref())",
"value": [
{
"Id": "PG1",
"Name": "Food",
"Products": [
{
"@odata.id": "Products('P1')"
},
{
"@odata.id": "Products('P2')"
}
]
},
{
"Id": "PG2",
"Name": "Non-Food",
"Products": [
{
"@odata.id": "Products('P3')"
},
{
"@odata.id": "Products('P4')"
}
]
}
]
} Test 2:
Result: {
"@odata.context": "http://service/$metadata#Categories(Products/$ref())",
"value": [
{
"Id": "PG1",
"Name": "Food",
"Products": [
{
"@odata.id": "Products('P1')"
}
]
},
{
"Id": "PG2",
"Name": "Non-Food",
"Products": [
{
"@odata.id": "Products('P3')"
}
]
}
]
} Test 3:
Result: {
"@odata.context": "http://service/$metadata#Categories(Products/$ref())",
"value": [
{
"Id": "PG1",
"Name": "Food",
"Products": [
{
"@odata.id": "Products('P1')"
},
{
"@odata.id": "Products('P2')"
}
]
},
{
"Id": "PG2",
"Name": "Non-Food",
"Products": [
{
"@odata.id": "Products('P3')"
},
{
"@odata.id": "Products('P4')"
}
]
}
]
} I don't know if I'm doing something wrong. Can you verify whether you get the expected results against a sample service? |
@gathogojr I have added this feature to OData Core. We will support it in WebApi later. |
argh... I jumped the gun without even realizing it! |
This PR has Quantification details
Why proper sizing of changes matters
Optimal pull request sizes drive a better predictable PR flow as they strike a
What can I do to optimize my changes
How to interpret the change counts in git diff output
Was this comment helpful? 👍 :ok_hand: :thumbsdown: (Email) |
if (this.lexer.CurrentToken.Text.StartsWith("$", StringComparison.Ordinal) | ||
&& (!allowRef || this.lexer.CurrentToken.Text != UriQueryConstants.RefSegment) | ||
&& this.lexer.CurrentToken.Text != UriQueryConstants.CountSegment) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you explain the logic here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If Path segment starts with $
, it should only have $count
or $ref
when allowRef
is true
e.g
$expand=NavProp/$ref
$expand=NavProp/$count
/// <summary> | ||
/// Create an Expand item using a nav prop, its entity set and a SelectExpandClause | ||
/// </summary> | ||
/// <param name="pathToNavigationProperty">the path to the navigation property for this expand item, including any type segments</param> | ||
/// <param name="navigationSource">the navigation source for this ExpandItem</param> | ||
/// <param name="filterOption">A filter clause for this expand (can be null)</param> | ||
/// <param name="searchOption">A search clause for this expand (can be null)</param> | ||
/// <exception cref="System.ArgumentNullException">Throws if input pathToNavigationProperty is null.</exception> | ||
public ExpandedCountSelectItem(ODataExpandPath pathToNavigationProperty, IEdmNavigationSource navigationSource, FilterClause filterOption, SearchClause searchOption) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be helpful if you could provide an concrete example of a path that this class represents, and how the parts of the path that the different parameters represent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Issues
This pull request fixes issue #xxx.
Description
Add support for
$count
in Navigation properties.We are adding a new
PathSelectItem
namedExpandedCountSelectItem
which inherits fromExpandedReferenceSelectItem
.The
ExpandedCountSelectItem
only supports 2 query options,$filter
and$search
. See spec http://docs.oasis-open.org/odata/odata/v4.01/cs01/part1-protocol/odata-v4.01-cs01-part1-protocol.html#sec_RequestingtheNumberofItemsinaCollectChecklist (Uncheck if it is not completed)
Additional work necessary
If documentation update is needed, please add "Docs Needed" label to the issue and provide details about the required document change in the issue.