Skip to content

Commit 2b3d8f6

Browse files
committed
Added notes on what I think needs to happen to support NavigationPropertyBindings
1 parent 0ccadf8 commit 2b3d8f6

File tree

1 file changed

+70
-4
lines changed

1 file changed

+70
-4
lines changed

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

Lines changed: 70 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,14 @@ public string GetPostAsyncMethod(OdcmProperty odcmProperty, string requestBody =
137137

138138
public string GetImplicitNavigationPropertyUrlSegment(OdcmSingleton singleton, OdcmProperty odcmProperty)
139139
{
140+
/****
141+
To help the future dev in figuring this out, put a break point on the next executable line
142+
with the condition odcmProperty.Name == "teachers". The CSDL in and entities mentioned in these
143+
comments are an example of the use of this scenario.
144+
145+
****/
146+
147+
140148
// (1) Check that there are NavigationPropertyBindings. If there aren't any, then we know this segment of
141149
// the canonical path to the reference.
142150
if (singleton.NavigationPropertyBindings.Count == 0)
@@ -145,13 +153,13 @@ public string GetImplicitNavigationPropertyUrlSegment(OdcmSingleton singleton, O
145153
}
146154

147155
// (2) Get all of the keys that contain our target path name. The keys come from the Path attribute on a
148-
// NavigationPropertyBinding. So if our target property (OdcmProperty.Name) is named 'schools', then we need to only consider
149-
// NavigationPropertyBinding paths that end with 'schools'. The NavigationPropertyBindings are found in the Singleton that
156+
// NavigationPropertyBinding. So if our target property (OdcmProperty.Name) is named 'teachers', then we need to only consider
157+
// NavigationPropertyBinding paths that end with 'teachers'. The NavigationPropertyBindings are found in the Singleton that
150158
// defines the EntitySet that contains this property. The NavigationPropertyBindings provide generation hints for how to
151159
// reference non-contained entities that are defined within the same Singleton (this statement is conjecture). This generation
152160
// hints is used to specify a reference URL for $ref call.
153161

154-
// TODO DELETE: in this case, "teachers". This should be the end part of the BindingPath.
162+
// Example: in this case, "teachers". This should be the end part of the BindingPath.
155163

156164
IEnumerable<string> keys = singleton.NavigationPropertyBindings.Where(kvp => kvp.Key.EndsWith(odcmProperty.Name)).Select(kvp => kvp.Key);
157165
/*
@@ -164,18 +172,50 @@ public string GetImplicitNavigationPropertyUrlSegment(OdcmSingleton singleton, O
164172
<NavigationPropertyBinding Path="users/schools" Target="schools" />
165173
<NavigationPropertyBinding Path="users/classes" Target="classes" />
166174
</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>
167192
*/
168193

169194
// We need to support long NavPropBindings. That is, we need to support multi-segment NavigationPropertyBinding paths
170195
// (3) We need to query the paths in {keys} against the entity (odcmProperty.Class) that contains this navigation property (odcmProperty).
171196
// We need to determine the unique binding path from the singleton through the entity on to this navigation property, query the keys
172-
// for it, and then get the target. There could be 1 or more hops that we need to account for.
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.
173202

174203
// odcmProperty.Name; // --> "teachers"
175204

176205
var navPropClassToFind = odcmProperty.Class.Name; // -- > "educationClass"; This is the EntityType that contains the navigation property
177206
string firstBindingPathSegment = ""; // We are incorrectly assuming to segment.
178207

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+
179219
foreach (OdcmProperty prop in (singleton.Type as OdcmEntityClass).Properties)
180220
{
181221
if (prop.Type.Name == navPropClassToFind)
@@ -185,6 +225,32 @@ public string GetImplicitNavigationPropertyUrlSegment(OdcmSingleton singleton, O
185225
}
186226
}
187227

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+
188254
string secondBindingPathSegment = odcmProperty.Name;
189255

190256
//string bindingPath = firstBindingPathSegment + "/" + keys.First(); // TODO: Need to fix this.

0 commit comments

Comments
 (0)