how to get referencial data using odata - entity-relationship

I have two tables, NetworkAccount and Division. The are related by DivisionID
NetworkAccount has the full user information including a DivisionID
Division has all related information related to a division.
I have the users logon name, how can I retrive his DivisionName which is stored in the Division table. I want to do this with one query to the oData service.
I've tried the following and nothing is giving me the answer I wanted.
http://localhost:54471/NetworkInfo.svc/Divisions?$filter=Username eq 'test\name'
I get the following
<message xml:lang="en-CA">No property 'Username' exists in type 'NetworkInfoService.Division' at position 0.</message>
http://localhost:54471/NetworkInfo.svc/Divisions?$filter=NetworkAccount/Username eq 'test\name'
I get the following
<message xml:lang="en-CA">No property 'NetworkAccount' exists in type 'NetworkInfoService.Division' at position 0.</message>
But if I do the opposite, if I want to get users that belong to a certain division, it works no problem, see below.
localhost:54471/NetworkInfo.svc/NetworkAccounts?$filter=Division/Name eq 'SomeName'
Any help would be much appreciated.
Thanks

Could you please post the shape of the model for the Division and NetworkAccount types?
The typical way to do this in OData is a query like:
/NetworkAccounts(TheIDOfTheUserImLookingFor)/Division

Ok, I figured out the syntax... it goes like this:
http://localhost:12345/NetworkInfo.svc/NetworkAccounts?$filter=Username eq 'test\name'&$expand=Division
The $expand keyword is the trick.

Related

Get Microsoft Graph messages by flagStatus using OData $filter

I'm writing Microsoft Graph OData query to get mail messages based on message flagStatus in order to reuse working query in my C# code. How correct query should look like?
Following example is tried in Graph Explorer's sample account where all messages have object flag with field flagStatus = "notFlagged".
https://graph.microsoft.com/v1.0/me/messages?$filter=flag/flagStatus eq 'notFlagged'
It is expected that all messages should be returned. But as a result empty array was given back.
If in query I change eq to ne to be
https://graph.microsoft.com/v1.0/me/messages?$filter=flag/flagStatus ne 'notFlagged'
then all messages are returned. But by me it is expected that here should be empty array in this case.
Considering that maybe flag object isn't ready for filtering, I also tried to $expand it
https://graph.microsoft.com/v1.0/me/messages?$expand=flag&$filter=flag/flagStatus eq 'notFlagged'
but got error message
Property 'flag' on type 'microsoft.graph.message' is not a navigation property or complex property. Only navigation properties can be expanded.
So probably $expand for flag filtering is not needed. But is it possible to filter by message's flag at all?
Also if consider situation that flag object could be null and also flagStatus inside could be null (at least in C# class Microsoft.Graph.FollowupFlag property FlagStatus is nullable), then how query should look like to meet full requrirement below?
Get messages whose
flag is null
or flag/flagStatus is null
or flag/flagStatus is 'notFlagged'
I had the same problem, probably is nullable as suggested. There's only three possible statuses according to the followupFlag documentation, so I worked around it with a not equal and condition for the two other statuses, complete and flagged.
https://graph.microsoft.com/v1.0/me/messages?$filter=flag/flagStatus ne 'flagged' and flag/flagStatus ne 'complete'

Microsoft Graph API using filter on get sharepoint lists

I'm trying to filter on the sharepoint lists, but the semantics seems to be different to the default semantics.
What I already tried was (with $ and without; single quotes and no quotes):
https://graph.microsoft.com/v1.0/sites/root/lists?filter=name eq 'Something'
https://graph.microsoft.com/v1.0/sites/root/lists?$filter=name eq 'Something'
https://graph.microsoft.com/v1.0/sites/root/lists?filter=id eq 'CFFF1460-B4D7-419C-A921-61B5279BBDDC'
https://graph.microsoft.com/v1.0/sites/root/lists?$filter=id eq 'CFFF1460-B4D7-419C-A921-61B5279BBDDC'
https://graph.microsoft.com/v1.0/sites/root/lists?filter=id eq CFFF1460-B4D7-419C-A921-61B5279BBDDC
https://graph.microsoft.com/v1.0/sites/root/lists?$filter=id eq CFFF1460-B4D7-419C-A921-61B5279BBDDC
But everything returns an array containing all lists and not only the subset matching the desired criteria.
So how can I filter on sharepoint lists?
If you know the id of the list you want to filter and get a response for.
YOu can run a graph API query like this.
https://graph.microsoft.com/v1.0/sites/root/lists/{list-id}
This will give you data about that list.
Let me know if you need further details on this.
Unfortunately (like Marc already mentioned in the comments) it is not possible to filter on SharePoint lists. If you need to, you have to do it on the client side, by reading the list without any filter and make a LINQ statement (or something similar) on the received collection. Be aware that (like all collections in Graph) you don't get always all elements at once. Potentially you have to call the next link request from the last response and wade through more requests and elements till you find what you need.
So when you found what you need, it is a good idea to store the list id within a memory cache or Redis cache for faster lookups the next time, you need this information.

SAP Gateway $filter on $expand Entity

I've seen two post about the URL convention, but my question is specific to the SAP's Gateway implementation for OData web services assuming. When trying to use $filter in combination with $expand we get the error message:
Left hand expression of memberaccess operation has wrong cardinality
Assuming I have two simple entities:
Foo
* Key
- Value
Bar
* Key
* Id
- Value
Foo has a 1:n association to Bar. The following URL works as intended.
/sap/opu/odata/sap/ZTEST_SRV/Foo?$expand=Bar
As does
/sap/opu/odata/sap/ZTEST_SRV/Foo?$filter=Key gt 10&$expand=Bar
When trying to using $filter on entity Bar property Id we get the error message.
/sap/opu/odata/sap/ZTEST_SRV/Foo?$filter=Key gt 10 and Bar/Id gt 2&$expand=Bar
Is it possible to use a $filter in this way with SAP? Related articles below.
ODATA / SAP Gateway: About Query with $filter and $expand simultaneously
Filter on Expanded entities in OData
I am also facing similar problems, there is this sap note:
https://apps.support.sap.com/sap/support/knowledge/en/3008698
Copy of the note details:
BEGIN OF NOTE
Symptom
After adding a filter
$filter = To_Employees/Name eq 'Hugo' to an Odata service, there is an error:
"Left hand expression of memberaccess operator has wrong cardinality (to many not allowed)"
Environment
SAP_GWFND 750
Reproducing the Issue
Access the odata service: /sap/opu/odata/sap/API_XXX_SRV/Orgnization$select=Orgnization,to_Employees/Name&$expand=to_Employees&$filter=to_Employees/Name eq 'Hugo'
There is an error: "Left hand expression of memberaccess operator has wrong cardinality (to many not allowed)"
Cause
"Left hand expression of memberaccess operator has wrong cardinality (to many not allowed)" indicates that "to_Employees"is a to-many navigation, and this is not supported in combination with a filter expression (e.g.
$filter = To_Employees/Name eq 'Hugo',
when "To_Employees" points to more than one employee ).
Therefore, the whole request is invalid.
Resolution
Remove the filter, do not combine to many results with filter eq
END OF NOTE
I don't like the solution presented :)
The workaround solution I have implemented was to create an entity which has cardinality 1:1 just for filtering.
In your example, I assume you need the cardinaliy of the relationship from Foo to Bar to be 1:n in order to be able to receive multiple Bar records for each Foo found. If the relationship Foo to Bar is 1:1, you can simply change the cardinality and you are good to go. If you need cardinality 1:n, you may create an entity like BarFilter which is related to Foo with 1:1 cardinality. Then you would be able to execute this request without errors and can receive the filters to make the corresponding query on your backend system. The request would be something like:
New simple entity:
BarFilter
Key
Id
Value
Foo has a 1:1 association to new entity BarFilter.
Request:
/sap/opu/odata/sap/ZTEST_SRV/Foo?$filter=Key gt 10 and BarFilter/Id gt 2&$expand=Bar
I hope this is clear and that it helps you.
I am very interested in this topic so if you find something interesting, please share it.
Have a nice weekend.
Cheers

Dynamics CRM OData query filtering on expanded attributes only works if no results come out?

I have a requirement to fetch Price List Item records which adhere to the following requirements:
Filter by a specific PriceList
Filter by a specific currency
Filter by the Name of the related Product containing a given string
I got the first two points working no problem, but it feels like expanding doesn't cope well with filtering. I started from a "straight" query on Product entity:
.../ProductSet?$filter=substringof('sometext', Name)
Equivalent SQL (targeting the corresponding CRM filtered views for clarity):
SELECT * FROM FilteredProduct WHERE ProductNumber LIKE '%sometext%'
The above query works, I can tweak it and have no issues. However, if I attempt to move on to ProductPriceLevel (thus expanding the relationship with Product, which is product_price_levels) I end up with this:
.../ProductPriceLevelSet?$expand=product_price_levels&$filter=substringof('sometext', product_price_levels/Name)
Equivalent SQL (again, targeting the relevant filtered views):
SELECT * FROM FilteredProductPriceLevel PPL JOIN FilteredProduct P
ON PPL.ProductId = P.ProductId WHERE P.ProductNumber LIKE '%sometext%'
Which has two different outcomes I see:
If the $filter has no matches, it works fine and returns an empty result set
If the $filter matches something, I get an error
code: -2147220970
message: The result selector of the 'Join' operation must return an anonymous type of two properties.
AFAIK that's what happens when you hit a limitation of LINQ-to-CRM regarding using .Where() on multiple entities at once... doesn't seem relevant!
What's wrong with my query ?
NOTE: The CRM 2013 I'm using is On-Premise, without any update rollup / service pack.
ALSO NOTE: The equivalent SQL, as can be expected, works perfectly
I don't think CRM OData supports adding a filter on a joined entity. Try reversing the entity you're actually starting with, and add a path to the referencing entity:
ProductSet()?$filter=substringof('sometext',ProductNumber)&$expand=product_price_levels&$select=product_price_levels/*
P.S. If you have linqPad, this is the query I used to generate this:
from p in ProductSet
where p.ProductNumber.Contains("sometext")
select new { p.product_price_levels }

Can an OData query specify a filter that references a nested entity?

Here is the setup: I've got a "Student" who has a related entity "Course" (1 to many). Each "Course" has a related entity "Period" that contains all of the time and date details of the course. I want to get back all of the students who have had a course in 2011.
I've tried this:
~/Student()?$expand=Course/Period&$filter=Course/Period/Year eq 2011
but it results in an error: No property 'Period' exists in type 'System.Data.Objects.DataClasses.EntityCollection`1[[Course]]
Clearly, Period is being treated as a property rather than an Entity, but I'm confused, because the following query does return the results I expect, and it uses almost the same syntax:
~/Student()?$expand=Course/Period&$select=Course/Period/Year
So am I doing something wrong with the $filter syntax, or is this not possible?
TIA for any insight.
The filter would work if the navigation property would be a singleton, but since it's a collection (1 to many) the filter won't work. Mainly because it's unclear what would that mean. Do you want students which have all their courses in 2011 or just some... and so on.
In the latest CTP (http://blogs.msdn.com/b/astoriateam/archive/2011/06/30/announcing-wcf-data-services-june-2011-ctp-for-net4-amp-sl4.aspx) There's a support for any and all operators which should allow you to do what you want. For more details see this blog post: http://www.odata.org/blog/even-more-any-and-all.
Yes it should be possible. You need to use something like this.
~/Student()?$expand=Course/Period&$filter=Course/any(d:d/Period/Year eq 2011)
Course/any() looks to see if anything in the collection matches the expression in ().
d: specifies an iterator for the collection which is then referenced in the d/Period/Year.
Reference can be found in OData Documentation In Section 5.1.1.10.1 (Search for "/any").
Note: You can also do /all to ensure that all courses match some criteria.

Resources