/// <summary> /// Get the names of appropriate navigation properties from metadata. /// </summary> /// <param name="sc">The service context.</param> /// <param name="type">The navigation property type.</param> /// <returns>Returns the list of navigation property names.</returns> public static List<string> GetAppropriateNavigationPropertyNames(ServiceContext sc, NavigationPropertyType type) { if (sc == null) { return null; } List<string> result = new List<string>(); string xpath = string.Format("//*[local-name()='EntityType' and @Name='{0}']/*[local-name()='NavigationProperty']", sc.EntityTypeShortName); XElement metadata = XElement.Parse(sc.MetadataDocument); var navigProps = metadata.XPathSelectElements(xpath, ODataNamespaceManager.Instance); if (ODataVersion.V4 == sc.Version) { var collectionTypeNavigProps = NavigationPropertyType.SetOfEntities == type ? navigProps.Where(np => np.Attribute(@"Type").Value.Contains(@"Collection")) : navigProps.Where(np => !np.Attribute(@"Type").Value.Contains(@"Collection")); foreach (var ctnp in collectionTypeNavigProps) { result.Add(ctnp.Attribute(@"Name").Value); } } else { string typeFlag = NavigationPropertyType.SetOfEntities == type ? @"*" : @"0..1"; xpath = string.Format("//*[local-name()='EntityType' and @Name='{0}']", sc.EntityTypeShortName); XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(sc.MetadataDocument); XmlNode entityTypeNode = xmlDoc.SelectSingleNode(xpath, ODataNamespaceManager.Instance); string odataNamespace = string.Empty; if (null != entityTypeNode.ParentNode.Attributes[@"Namespace"]) { odataNamespace = entityTypeNode.ParentNode.Attributes[@"Namespace"].Value; } string associNameFilter = @"1!=1"; string toRoleNameFilter = @"1!=1"; foreach (var np in navigProps) { string associName = np.Attribute(@"Relationship").Value.Remove(0, (odataNamespace + @".").Length); associNameFilter += @" or " + string.Format(@"@Name='{0}'", associName); string toRoleName = np.Attribute(@"ToRole").Value; toRoleNameFilter += @" or " + string.Format(@"@Role='{0}'", toRoleName); } xpath = string.Format(@"//*[local-name()='Association'][{0}]/*[local-name()='End'][@Multiplicity='{1}' and ({2})]", associNameFilter, typeFlag, toRoleNameFilter); XmlNodeList endNodes = xmlDoc.SelectNodes(xpath, ODataNamespaceManager.Instance); List<string> toRoleNames = new List<string>(); foreach (XmlNode en in endNodes) { toRoleNames.Add(en.Attributes[@"Role"].Value); } foreach (var np in navigProps) { if (toRoleNames.Contains(np.Attribute(@"ToRole").Value)) { result.Add(np.Attribute(@"Name").Value); } } } return result; }
/// <summary> /// Get the URLs of entity sets which have a specified navigation property. /// </summary> /// <param name="sc">The service context.</param> /// <param name="navigPropType">The type of navigation property.</param> /// <returns>Returns a list contatins all the appropriate entity set URLs.</returns> public static List<string> GetEntitySetUrlsContainsCurrentEntityTypeName(ServiceContext sc, NavigationPropertyType navigPropType) { if (sc == null) { return new List<string>(); } string entityTypeNs = sc.EntityTypeFullName.RemoveEnd(sc.EntityTypeShortName); string target = NavigationPropertyType.SetOfEntities == navigPropType ? string.Format("Collection({0})", sc.EntityTypeFullName) : sc.EntityTypeFullName; string xpath = string.Format("//*[local-name()='EntityType']/*[local-name()='NavigationProperty' and @Type='{0}']", target); XElement metadata = XElement.Parse(sc.MetadataDocument); var navigProps = metadata.XPathSelectElements(xpath, ODataNamespaceManager.Instance).ToList(); if (navigProps == null) { return new List<string>(); } var entityTypeElementNames = new List<string>(); navigProps.ForEach(n => entityTypeElementNames.Add(entityTypeNs + n.Parent.Attribute("Name").Value)); xpath = @"//*[local-name()='EntityContainer']/*[local-name()='EntitySet']"; var allEntitySetElements = metadata.XPathSelectElements(xpath, ODataNamespaceManager.Instance).ToList(); if (allEntitySetElements == null) { return new List<string>(); } var entitySetElementNames = allEntitySetElements .FindAll(entitySet => entityTypeElementNames.Contains(entitySet.Attribute("EntityType").Value)) .Select(entitySet => entitySet.Attribute("Name").Value); JObject service = JObject.Parse(sc.ServiceDocument); var entities = JsonParserHelper.GetEntries(service).ToList(); if (entities == null) { return new List<string>(); } return entities.Where(e => entitySetElementNames.Contains(e["name"].ToString())).Select(e => e["url"].ToString()).ToList(); }
public static Dictionary<string, string> GetAppropriateNavigationPropertyNameAndType(string entityTypeName, string metadataDocument, NavigationPropertyType type) { Dictionary<string, string> result = new Dictionary<string, string>(); string xpath = string.Format("//*[local-name()='EntityType' and @Name='{0}']/*[local-name()='NavigationProperty']", entityTypeName); XElement metadata = XElement.Parse(metadataDocument); var navigProps = metadata.XPathSelectElements(xpath, ODataNamespaceManager.Instance); var collectionTypeNavigProps = NavigationPropertyType.SetOfEntities == type ? navigProps.Where(np => np.Attribute(@"Type").Value.Contains(@"Collection")) : navigProps.Where(np => !np.Attribute(@"Type").Value.Contains(@"Collection")); foreach (var ctnp in collectionTypeNavigProps) { result.Add(ctnp.GetAttributeValue("Name"), ctnp.GetAttributeValue("Type")); } return result; }