/// <summary> /// Finds the entity set that a navigation property targets. /// </summary> /// <param name="navigationProperty">The navigation property.</param> /// <param name="bindingPath">The binding path of the navigation property</param> /// <returns>The entity set that the navigation property targets</returns> public override IEdmNavigationSource FindNavigationTarget(IEdmNavigationProperty navigationProperty, IEdmPathExpression bindingPath) { // 7.4.1 expected the path to be prefixed with the path to the contained navigation source. // For backward compatibility, if the binding path received starts with the path to this contained resource, // we trim it off and then treat the remainder as the path to the target. This logic should be removed in // the next breaking change as it could be ambiguous in the case that the prefix of the path to the contained // source matches a valid path to the target of the contained source. if (bindingPath != null) { if (bindingPath.Path.Length > this.FullNavigationPath.Length && bindingPath.Path.StartsWith(this.FullNavigationPath, System.StringComparison.Ordinal)) { bindingPath = new EdmPathExpression(bindingPath.Path.Substring(this.FullNavigationPath.Length + 1)); } } IEdmNavigationSource navigationTarget = base.FindNavigationTarget(navigationProperty, bindingPath); if (navigationTarget is IEdmUnknownEntitySet) { IEnumerable <string> segments = (bindingPath == null || string.IsNullOrEmpty(bindingPath.Path)) ? new string[] { navigationProperty.Name } : bindingPath.PathSegments; bindingPath = new EdmPathExpression(this.NavigationPath.PathSegments.Concat(segments)); return(this.parentNavigationSource.FindNavigationTarget(navigationProperty, bindingPath)); } return(navigationTarget); }
private void BuildOperations(EdmModel model, string modelNamespace) { foreach (var operationMethodInfo in operationInfos) { // With this method, if return type is nullable type,it will get underlying type var returnType = TypeHelper.GetUnderlyingTypeOrSelf(operationMethodInfo.Method.ReturnType); var returnTypeReference = returnType.GetReturnTypeReference(model); var isBound = operationMethodInfo.IsBound; var bindingParameter = operationMethodInfo.Method.GetParameters().FirstOrDefault(); if (bindingParameter == null && isBound) { // Ignore the method which is marked as bounded but no parameters continue; } var namespaceName = GetNamespaceName(operationMethodInfo, modelNamespace); EdmOperation operation = null; EdmPathExpression path = null; if (isBound) { // Unbound actions or functions should not have EntitySetPath attribute path = BuildBoundOperationReturnTypePathExpression(returnTypeReference, bindingParameter); } if (operationMethodInfo.HasSideEffects) { operation = new EdmAction(namespaceName, operationMethodInfo.Name, returnTypeReference, isBound, path); } else { operation = new EdmFunction(namespaceName, operationMethodInfo.Name, returnTypeReference, isBound, path, operationMethodInfo.IsComposable); } BuildOperationParameters(operation, operationMethodInfo.Method, model); model.AddElement(operation); if (!isBound) { // entitySetReferenceExpression refer to an entity set containing entities returned // by this function/action import. var entitySetExpression = BuildEntitySetExpression( model, operationMethodInfo.EntitySet, returnTypeReference); var entityContainer = model.EnsureEntityContainer(targetType); if (operationMethodInfo.HasSideEffects) { entityContainer.AddActionImport(operation.Name, (EdmAction)operation, entitySetExpression); } else { entityContainer.AddFunctionImport( operation.Name, (EdmFunction)operation, entitySetExpression); } } } }