@@ -102,7 +102,7 @@ protected virtual void Initialize(IEdmModel model)
102102
103103 private IEnumerable < ODataPath > MergePaths ( )
104104 {
105- List < ODataPath > allODataPaths = new List < ODataPath > ( ) ;
105+ List < ODataPath > allODataPaths = new ( ) ;
106106 foreach ( var item in _allNavigationSourcePaths . Values )
107107 {
108108 allODataPaths . AddRange ( item ) ;
@@ -127,6 +127,7 @@ private void AppendPath(ODataPath path)
127127 ODataPathKind kind = path . Kind ;
128128 switch ( kind )
129129 {
130+ case ODataPathKind . DollarCount :
130131 case ODataPathKind . Entity :
131132 case ODataPathKind . EntitySet :
132133 case ODataPathKind . Singleton :
@@ -143,8 +144,7 @@ private void AppendPath(ODataPath path)
143144
144145 case ODataPathKind . NavigationProperty :
145146 case ODataPathKind . Ref :
146- ODataNavigationPropertySegment navigationPropertySegment = path . Last ( p => p is ODataNavigationPropertySegment )
147- as ODataNavigationPropertySegment ;
147+ ODataNavigationPropertySegment navigationPropertySegment = path . OfType < ODataNavigationPropertySegment > ( ) . Last ( ) ;
148148
149149 if ( ! _allNavigationPropertyPaths . TryGetValue ( navigationPropertySegment . EntityType , out IList < ODataPath > npList ) )
150150 {
@@ -174,15 +174,17 @@ private void RetrieveNavigationSourcePaths(IEdmNavigationSource navigationSource
174174 Debug . Assert ( navigationSource != null ) ;
175175
176176 // navigation source itself
177- ODataPath path = new ODataPath ( new ODataNavigationSourceSegment ( navigationSource ) ) ;
177+ ODataPath path = new ( new ODataNavigationSourceSegment ( navigationSource ) ) ;
178178 AppendPath ( path . Clone ( ) ) ;
179179
180180 IEdmEntitySet entitySet = navigationSource as IEdmEntitySet ;
181181 IEdmEntityType entityType = navigationSource . EntityType ( ) ;
182182
183- // for entity set, create a path with key
183+ // for entity set, create a path with key and a $count path
184184 if ( entitySet != null )
185185 {
186+ CreateCountPath ( path ) ;
187+
186188 path . Push ( new ODataKeySegment ( entityType ) ) ;
187189 AppendPath ( path . Clone ( ) ) ;
188190 }
@@ -275,6 +277,13 @@ private void RetrieveNavigationPropertyPaths(IEdmNavigationProperty navigationPr
275277 if ( restriction == null || restriction . IndexableByKey == true )
276278 {
277279 IEdmEntityType navEntityType = navigationProperty . ToEntityType ( ) ;
280+ var targetsMany = navigationProperty . TargetMultiplicity ( ) == EdmMultiplicity . Many ;
281+
282+ if ( targetsMany )
283+ {
284+ // ~/entityset/{key}/collection-valued-Nav/$count
285+ CreateCountPath ( currentPath ) ;
286+ }
278287
279288 if ( ! navigationProperty . ContainsTarget )
280289 {
@@ -283,7 +292,7 @@ private void RetrieveNavigationPropertyPaths(IEdmNavigationProperty navigationPr
283292 // Collection-valued: ~/entityset/{key}/collection-valued-Nav/$ref?$id ={navKey}
284293 CreateRefPath ( currentPath ) ;
285294
286- if ( navigationProperty . TargetMultiplicity ( ) == EdmMultiplicity . Many )
295+ if ( targetsMany )
287296 {
288297 // Collection-valued: DELETE ~/entityset/{key}/collection-valued-Nav/{key}/$ref
289298 currentPath . Push ( new ODataKeySegment ( navEntityType ) ) ;
@@ -296,7 +305,7 @@ private void RetrieveNavigationPropertyPaths(IEdmNavigationProperty navigationPr
296305 else
297306 {
298307 // append a navigation property key.
299- if ( navigationProperty . TargetMultiplicity ( ) == EdmMultiplicity . Many )
308+ if ( targetsMany )
300309 {
301310 currentPath . Push ( new ODataKeySegment ( navEntityType ) ) ;
302311 AppendPath ( currentPath . Clone ( ) ) ;
@@ -318,7 +327,7 @@ private void RetrieveNavigationPropertyPaths(IEdmNavigationProperty navigationPr
318327 }
319328 }
320329
321- if ( navigationProperty . TargetMultiplicity ( ) == EdmMultiplicity . Many )
330+ if ( targetsMany )
322331 {
323332 currentPath . Pop ( ) ;
324333 }
@@ -360,6 +369,16 @@ private void CreateRefPath(ODataPath currentPath)
360369 newPath . Push ( ODataRefSegment . Instance ) ; // $ref
361370 AppendPath ( newPath ) ;
362371 }
372+ /// <summary>
373+ /// Create $count paths.
374+ /// </summary>
375+ /// <param name="currentPath">The current OData path.</param>
376+ private void CreateCountPath ( ODataPath currentPath ) {
377+ if ( currentPath == null ) throw new ArgumentNullException ( nameof ( currentPath ) ) ;
378+ var countPath = currentPath . Clone ( ) ;
379+ countPath . Push ( ODataDollarCountSegment . Instance ) ;
380+ AppendPath ( countPath ) ;
381+ }
363382
364383 /// <summary>
365384 /// Retrieve all bounding <see cref="IEdmOperation"/>.
@@ -436,7 +455,11 @@ private void RetrieveBoundOperationPaths(OpenApiConvertSettings convertSettings)
436455 }
437456 }
438457 }
439-
458+ private static readonly HashSet < ODataPathKind > _oDataPathKindsToSkipForOperations = new HashSet < ODataPathKind > ( ) {
459+ ODataPathKind . EntitySet ,
460+ ODataPathKind . MediaEntity ,
461+ ODataPathKind . DollarCount
462+ } ;
440463 private bool AppendBoundOperationOnNavigationSourcePath ( IEdmOperation edmOperation , bool isCollection , IEdmEntityType bindingEntityType )
441464 {
442465 bool found = false ;
@@ -448,8 +471,7 @@ private bool AppendBoundOperationOnNavigationSourcePath(IEdmOperation edmOperati
448471 foreach ( var subPath in value )
449472 {
450473 if ( ( isCollection && subPath . Kind == ODataPathKind . EntitySet ) ||
451- ( ! isCollection && subPath . Kind != ODataPathKind . EntitySet &&
452- subPath . Kind != ODataPathKind . MediaEntity ) )
474+ ( ! isCollection && ! _oDataPathKindsToSkipForOperations . Contains ( subPath . Kind ) ) )
453475 {
454476 ODataPath newPath = subPath . Clone ( ) ;
455477 newPath . Push ( new ODataOperationSegment ( edmOperation , isEscapedFunction ) ) ;
@@ -461,21 +483,18 @@ private bool AppendBoundOperationOnNavigationSourcePath(IEdmOperation edmOperati
461483
462484 return found ;
463485 }
464-
486+ private static readonly HashSet < ODataPathKind > _pathKindToSkipForNavigationProperties = new ( ) {
487+ ODataPathKind . Ref ,
488+ } ;
465489 private bool AppendBoundOperationOnNavigationPropertyPath ( IEdmOperation edmOperation , bool isCollection , IEdmEntityType bindingEntityType )
466490 {
467491 bool found = false ;
468492 bool isEscapedFunction = _model . IsUrlEscapeFunction ( edmOperation ) ;
469493
470494 if ( _allNavigationPropertyPaths . TryGetValue ( bindingEntityType , out IList < ODataPath > value ) )
471495 {
472- foreach ( var path in value )
496+ foreach ( var path in value . Where ( x => ! _pathKindToSkipForNavigationProperties . Contains ( x . Kind ) ) )
473497 {
474- if ( path . Kind == ODataPathKind . Ref )
475- {
476- continue ;
477- }
478-
479498 ODataNavigationPropertySegment npSegment = path . Segments . Last ( s => s is ODataNavigationPropertySegment ) as ODataNavigationPropertySegment ;
480499
481500 if ( ! npSegment . NavigationProperty . ContainsTarget )
@@ -596,15 +615,9 @@ private bool AppendBoundOperationOnDerivedNavigationPropertyPath(
596615 {
597616 if ( _allNavigationPropertyPaths . TryGetValue ( baseType , out IList < ODataPath > paths ) )
598617 {
599- foreach ( var path in paths )
618+ foreach ( var path in paths . Where ( x => ! _pathKindToSkipForNavigationProperties . Contains ( x . Kind ) ) )
600619 {
601- if ( path . Kind == ODataPathKind . Ref )
602- {
603- continue ;
604- }
605-
606- var npSegment = path . Segments . Last ( s => s is ODataNavigationPropertySegment )
607- as ODataNavigationPropertySegment ;
620+ var npSegment = path . Segments . OfType < ODataNavigationPropertySegment > ( ) . LastOrDefault ( ) ;
608621 if ( npSegment == null )
609622 {
610623 continue ;
0 commit comments