Skip to content

Commit 953deb2

Browse files
committed
Cleaned up code and notes and stated assumptions for how we process NavigationPropertyBindings to generate the reference URL.
1 parent 2b3d8f6 commit 953deb2

File tree

1 file changed

+8
-98
lines changed

1 file changed

+8
-98
lines changed

Templates/CSharp/Base/CollectionRequest.Base.template.tt

Lines changed: 8 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,9 @@ public string GetImplicitNavigationPropertyUrlSegment(OdcmSingleton singleton, O
141141
To help the future dev in figuring this out, put a break point on the next executable line
142142
with the condition odcmProperty.Name == "teachers". The CSDL in and entities mentioned in these
143143
comments are an example of the use of this scenario.
144-
145144
****/
146145

147-
148-
// (1) Check that there are NavigationPropertyBindings. If there aren't any, then we know this segment of
146+
// (1) Check that there are NavigationPropertyBindings. If there aren't any, then we know this segment is
149147
// the canonical path to the reference.
150148
if (singleton.NavigationPropertyBindings.Count == 0)
151149
{
@@ -158,107 +156,19 @@ public string GetImplicitNavigationPropertyUrlSegment(OdcmSingleton singleton, O
158156
// defines the EntitySet that contains this property. The NavigationPropertyBindings provide generation hints for how to
159157
// reference non-contained entities that are defined within the same Singleton (this statement is conjecture). This generation
160158
// hints is used to specify a reference URL for $ref call.
161-
162159
// Example: in this case, "teachers". This should be the end part of the BindingPath.
163160

164161
IEnumerable<string> keys = singleton.NavigationPropertyBindings.Where(kvp => kvp.Key.EndsWith(odcmProperty.Name)).Select(kvp => kvp.Key);
165-
/*
166-
<Singleton Name="education" Type="microsoft.graph.educationRoot">
167-
<NavigationPropertyBinding Path="classes/teachers" Target="users" />
168-
<NavigationPropertyBinding Path="classes/members" Target="users" />
169-
<NavigationPropertyBinding Path="classes/schools" Target="schools" />
170-
<NavigationPropertyBinding Path="schools/classes" Target="classes" />
171-
<NavigationPropertyBinding Path="schools/users" Target="users" />
172-
<NavigationPropertyBinding Path="users/schools" Target="schools" />
173-
<NavigationPropertyBinding Path="users/classes" Target="classes" />
174-
</Singleton>
175-
176-
<EntityType Name="educationRoot" BaseType="microsoft.graph.entity">
177-
<NavigationProperty Name="synchronizationProfiles" Type="Collection(microsoft.graph.educationSynchronizationProfile)" ContainsTarget="true" />
178-
<NavigationProperty Name="classes" Type="Collection(microsoft.graph.educationClass)" ContainsTarget="true" />
179-
<NavigationProperty Name="schools" Type="Collection(microsoft.graph.educationSchool)" ContainsTarget="true" />
180-
<NavigationProperty Name="users" Type="Collection(microsoft.graph.educationUser)" ContainsTarget="true" />
181-
<NavigationProperty Name="me" Type="microsoft.graph.educationUser" ContainsTarget="true" />
182-
</EntityType>
183-
184-
<EntityType Name="educationClass" BaseType="microsoft.graph.entity">
185-
<Property Name="displayName" Type="Edm.String" Nullable="false" />
186-
<NavigationProperty Name="schools" Type="Collection(microsoft.graph.educationSchool)" />
187-
<NavigationProperty Name="members" Type="Collection(microsoft.graph.educationUser)" />
188-
<NavigationProperty Name="teachers" Type="Collection(microsoft.graph.educationUser)" />
189-
<NavigationProperty Name="group" Type="microsoft.graph.group" />
190-
<NavigationProperty Name="assignments" Type="Collection(microsoft.graph.educationAssignment)" ContainsTarget="true" />
191-
</EntityType>
192-
*/
193-
194-
// We need to support long NavPropBindings. That is, we need to support multi-segment NavigationPropertyBinding paths
195-
// (3) We need to query the paths in {keys} against the entity (odcmProperty.Class) that contains this navigation property (odcmProperty).
196-
// We need to determine the unique binding path from the singleton through the entity on to this navigation property, query the keys
197-
// for it, and then get the target. There could be 1 or more pat segments that we need to account for.
198-
// Example: odcmProperty.Class is the entity "educationClass" that has the non-contained navigation property represented by odcmProperty,
199-
// which is named 'teachers'. At this point, we know the singleton and all of its NavigationPropertyBindings, we know the singleton's entity type,
200-
// which is named 'educationRoot'.
201-
// We need to determine whether a NavigationPropertyBinding pth and target is different than the CSDL described path to the reference non-contained entity.
202-
203-
// odcmProperty.Name; // --> "teachers"
204-
205-
var navPropClassToFind = odcmProperty.Class.Name; // -- > "educationClass"; This is the EntityType that contains the navigation property
206-
string firstBindingPathSegment = ""; // We are incorrectly assuming to segment.
207-
208-
// Get the path segments.
209-
//string[] navPropBindingSegments = keys.First().Split('/');
210-
211-
// Example: After hitting the conditional breakpoint, singleton.Type.Name is "educationRoot".
212-
// We are going to inspect each navigation property on singleton's type and compare to the segments
213-
// in the keys IEnumerable.
214-
// The assumption here is that the first segment is a navigation property of the singleton's type
215-
// The second assumption is that there are only two segments. We know this is a bad assumption.
216-
// The third assumption is that the last segment is the most meaningful.
217-
// In short, this only works for a Path that has two segments.
218-
219-
foreach (OdcmProperty prop in (singleton.Type as OdcmEntityClass).Properties)
220-
{
221-
if (prop.Type.Name == navPropClassToFind)
222-
{
223-
firstBindingPathSegment = prop.Name;
224-
break;
225-
}
226-
}
227-
228-
/*
229-
What we know.
230-
231-
We know the navigation property name and type.
232-
We know whih entity contains the navigation property.
233-
We know that the navigation property does not contain the entity.
234-
We know which singleton is the entity set for the navigation property.
235-
We know the singleton's type.
236-
We know the NavigationPropertyBindings and which candidates CAN be the one to define the reference path to the entity in the navigation.
237-
238-
We don't know the paths to the entity that contains our navigation property. So, the question is, can we know the context in which the
239-
navigation property is being accessed at generation time? I don't think we can.
240-
241-
The next question is can we code the templates to generate code that is context aware and can create the ref path based on that context.
242-
This is a maybe.
243-
244-
Our current example works since the scenario only has two levels of entities. What happens when we have three level of entities like
245-
/schools/classes/teachers. We know the teachers segments. We don't have context which entities are accessed across the request builders
246-
at runtime.
247-
248-
We may need to generate a dictionary from the NavPropBindings in to the code files and use those at runtime to discover the context in
249-
which a navigtion is called in order to provide the correct reference path.
250-
251-
TODO: investigate what it would take to generate code that is context aware of binding path.
252-
*/
253-
254-
string secondBindingPathSegment = odcmProperty.Name;
255-
256-
//string bindingPath = firstBindingPathSegment + "/" + keys.First(); // TODO: Need to fix this.
257-
string bindingPath = firstBindingPathSegment + "/" + secondBindingPathSegment;
258162

259163
string bindingTarget;
260164

261-
if (singleton.NavigationPropertyBindings.TryGetValue(bindingPath, out bindingTarget))
165+
// The first assumption is that CSDL is added with a convention where the last path segment in NavigationPropertyBinding.Path
166+
// is named consistently in a singleton so it doesn't matter what the preceding segments are.
167+
// The second assumption is that if the last path is named consistently, the target will be consistent as well.
168+
// These may turn out to be a weak assumption. We use this assumption since we can't determine a unique path
169+
// for three or more segments since *RequestBuilder and *Request objects are generated per entity+navigation,
170+
// and not [entity+navigation]*n --> across multiple navigations.
171+
if (keys.Count() > 0 && singleton.NavigationPropertyBindings.TryGetValue(keys.First(), out bindingTarget))
262172
{
263173
// We found the target
264174
return "/" + bindingTarget;

0 commit comments

Comments
 (0)