/// <summary> /// Gets a list of groups surrounding the specified geopoint of the specified GroupTypeid /// If geofenceGroupTypeId is specified, the list of GeoFence groups will be returned with the groups as child groups of that geofence group. /// </summary> /// <param name="groupTypeId">The group type identifier.</param> /// <param name="geoPoint">The geo point.</param> /// <param name="sortByDistance">if set to <c>true</c> [sort by distance].</param> /// <param name="maxDistanceMiles">The maximum distance miles.</param> /// <param name="geofenceGroupTypeId">The geofence group type identifier.</param> /// <param name="queryOptions">The query options.</param> /// <returns></returns> private IQueryable GetByGeoPoint( int groupTypeId, DbGeography geoPoint, bool? sortByDistance, double? maxDistanceMiles, int? geofenceGroupTypeId, System.Web.Http.OData.Query.ODataQueryOptions<Group> queryOptions ) { var rockContext = (RockContext)Service.Context; IEnumerable<Group> resultGroups = new List<Group>(); if ( geoPoint != null ) { if ( geofenceGroupTypeId.HasValue && geofenceGroupTypeId.Value > 0 ) { var fenceGroups = new List<Group>(); // Find all the groupLocation records ( belonging to groups of the "geofenceGroupType" ) // where the geofence surrounds the location var groupLocationService = new GroupLocationService( rockContext ); foreach ( var fenceGroupLocation in groupLocationService .Queryable( "Group,Location" ).AsNoTracking() .Where( gl => gl.Group.GroupTypeId == geofenceGroupTypeId && gl.Location.GeoFence != null && geoPoint.Intersects( gl.Location.GeoFence ) ) .ToList() ) { var fenceGroup = fenceGroups.FirstOrDefault( g => g.Id == fenceGroupLocation.GroupId ); if ( fenceGroup == null ) { fenceGroup = fenceGroupLocation.Group; fenceGroups.Add( fenceGroup ); } fenceGroupLocation.Group = null; // Find all the group groupLocation records ( with group of the "groupTypeId" ) that have a location // within the fence foreach ( var group in Service .Queryable( "Schedule,GroupLocations.Location" ).AsNoTracking() .Where( g => g.GroupTypeId == groupTypeId && g.GroupLocations.Any( gl => gl.Location.GeoPoint != null && gl.Location.GeoPoint.Intersects( fenceGroupLocation.Location.GeoFence ) ) ) ) { // Remove any other group locations that do not belong to fence foreach ( var gl in group.GroupLocations.ToList() ) { if ( gl.Location.GeoPoint == null || !gl.Location.GeoPoint.Intersects( fenceGroupLocation.Location.GeoFence ) ) { group.GroupLocations.Remove( gl ); } } fenceGroup.Groups.Add( group ); } } resultGroups = fenceGroups; } else { // if a geoFence is not specified, just get all groups of this group type resultGroups = Service.Queryable( "Schedule,GroupLocations.Location" ).AsNoTracking().Where( a => a.GroupTypeId == groupTypeId ).Include( a => a.GroupLocations ).ToList(); } } // calculate the distance of each of the groups locations from the specified geoFence foreach ( var group in resultGroups ) { foreach ( var gl in group.GroupLocations ) { // Calculate distance if ( gl.Location.GeoPoint != null ) { double meters = gl.Location.GeoPoint.Distance( geoPoint ) ?? 0.0D; gl.Location.SetDistance( meters * Location.MilesPerMeter ); } } } // remove groups that don't have a GeoPoint resultGroups = resultGroups.Where( a => a.GroupLocations.Any( x => x.Location.GeoPoint != null ) ); // remove groups that don't have a location within the specified radius if ( maxDistanceMiles.HasValue ) { resultGroups = resultGroups.Where( a => a.GroupLocations.Any( x => x.Location.Distance <= maxDistanceMiles.Value ) ); } var querySettings = new System.Web.Http.OData.Query.ODataQuerySettings(); if ( sortByDistance.HasValue && sortByDistance.Value ) { resultGroups = resultGroups.OrderBy( a => a.GroupLocations.FirstOrDefault() != null ? a.GroupLocations.FirstOrDefault().Location.Distance : int.MaxValue ).ToList(); // if we are sorting by distance, tell OData not to re-sort them by Id querySettings.EnsureStableOrdering = false; } // manually apply any OData parameters to the InMemory Query var qryResults = queryOptions.ApplyTo( resultGroups.AsQueryable(), querySettings ); return qryResults.AsQueryable(); }
/// <summary> /// Gets the collection of records for the requested entity set and specified OData query options. /// </summary> /// <param name="model"><see cref="IEdmModel"/></param> /// <param name="entitySetName">Name of the entity set</param> /// <param name="queryOptions"><see cref="System.Web.Http.OData.Query.ODataQueryOptions"/></param> /// <param name="querySettings"><see cref="System.Web.Http.OData.Query.ODataQuerySettings"/></param> /// <param name="request"><see cref="HttpRequestMessage"/></param> /// <returns><see cref="EdmEntityObjectCollection"/></returns> public virtual EdmEntityObjectCollection SelectMultiple(IEdmModel model, string entitySetName, System.Web.Http.OData.Query.ODataQueryOptions queryOptions, System.Web.Http.OData.Query.ODataQuerySettings querySettings, HttpRequestMessage request) { var edmEntitySchemaType = model.FindDeclaredType(string.Format("{0}.{1}", NamespaceName, entitySetName)); var edmEntityType = edmEntitySchemaType as IEdmEntityType; var entityListIdProperty = edmEntityType.FindProperty("list-id") as IEdmStructuralProperty; var entityListIdString = entityListIdProperty.DefaultValueString; var viewIdProperty = edmEntityType.FindProperty("view-id") as IEdmStructuralProperty; var viewIdString = viewIdProperty.DefaultValueString; var entityPermissionEnabledProperty = edmEntityType.FindProperty("entity-permissions-enabled") as IEdmStructuralProperty; bool entityPermissionsEnabled; bool.TryParse(entityPermissionEnabledProperty.DefaultValueString, out entityPermissionsEnabled); Guid viewId; Guid.TryParse(viewIdString, out viewId); var view = GetView(viewId); var viewColumns = view.Columns.ToList(); var fetch = Fetch.Parse(view.FetchXml); queryOptions.ApplyTo(querySettings, fetch); var serviceContext = this.Dependencies.GetServiceContext(); // If Entity Permissions on the view was enabled then restrict add entity Permissions to Fetch if (entityPermissionsEnabled) { var crmEntityPermissionProvider = new CrmEntityPermissionProvider(); var perm = crmEntityPermissionProvider.TryApplyRecordLevelFiltersToFetch( serviceContext, CrmEntityPermissionRight.Read, fetch); // Ensure the user has permissions to request read access to the entity. if (!perm.PermissionGranted && !perm.GlobalPermissionGranted) { ADXTrace.Instance.TraceWarning( TraceCategory.Exception, string.Format( "Access to oData, with the entity set name of '{0}', has been denied for the user with the following webroles: '{1}' due to entity permissions. Grant the webroles read access to the entityset if this was not an error.", entitySetName, string.Join("', '", crmEntityPermissionProvider.CurrentUserRoleNames))); throw new SecurityAccessDeniedException(); } } var dataSchemaType = model.FindDeclaredType(string.Format("{0}.{1}", NamespaceName, entitySetName)); var dataEntityType = dataSchemaType as IEdmEntityType; var dataEntityTypeReference = new EdmEntityTypeReference(dataEntityType, true); var collection = new EdmEntityObjectCollection(new EdmCollectionTypeReference(new EdmCollectionType(dataEntityTypeReference), true)); var entityReferenceSchemaType = model.FindDeclaredType(string.Format("{0}.{1}", NamespaceName, "EntityReference")); var entityReferenceComplexType = entityReferenceSchemaType as IEdmComplexType; var entityReferenceComplexTypeReference = new EdmComplexTypeReference(entityReferenceComplexType, true); var optionSetSchemaType = model.FindDeclaredType(string.Format("{0}.{1}", NamespaceName, "OptionSet")); var optionSetComplexType = optionSetSchemaType as IEdmComplexType; var optionSetComplexTypeReference = new EdmComplexTypeReference(optionSetComplexType, true); var entityCollection = fetch.Execute(serviceContext as IOrganizationService); if (entityCollection == null) { return(collection); } var records = entityCollection.Entities; foreach (var record in records) { var entityObject = BuildEdmEntityObject(record, view, viewColumns, dataEntityTypeReference, entityReferenceComplexTypeReference, optionSetComplexTypeReference, entityListIdString, viewIdString); collection.Add(entityObject); } if (entityCollection.MoreRecords && querySettings.PageSize.HasValue && querySettings.PageSize > 0) { var nextPageLink = ODataQueryOptionExtensions.GetNextPageLink(request, querySettings.PageSize.Value); request.SetNextPageLink(nextPageLink); } if (entityCollection.TotalRecordCount > 0) { request.SetInlineCount(entityCollection.TotalRecordCount); } return(collection); }