public void FilterBySpatialFunctionWithProperties() { var testCases = new[] { Tuple.Create("eq 1", 4), Tuple.Create("ne 2", 4), Tuple.Create("gt 2", 0), }; foreach (var t in testCases) { this.serviceFactory.SetRequestUri("Entities?$filter=geo.distance(Point, geography'SRID=1234;POINT(20 10)') " + t.Item1); var service = this.serviceFactory.CreateService(); RequestDescription d = RequestUriProcessor.ProcessRequestUri(this.serviceFactory.RequestUri, service, false); Action <GeographyPoint> verifyPoint = p => { Assert.AreEqual(20.0, p.Longitude); Assert.AreEqual(10.0, p.Latitude); }; RunSpatialDistanceFilterTest(d, null, verifyPoint, 1.0, t.Item2); } }
private void RunSpatialExpressionTest(string queryOption, string queryOptionValue, Expression <Func <IQueryable <TestEntityType>, IQueryable <TestEntityType> > > expectedExpressionPattern) { this.serviceFactory.SetRequestUri("Entities?" + queryOption + "=" + queryOptionValue); var service = this.serviceFactory.CreateService(); var d = RequestUriProcessor.ProcessRequestUri(this.serviceFactory.RequestUri, service, false); var actualQueryableMethodExpression = (MethodCallExpression)d.RequestExpression; var expectedString = expectedExpressionPattern.ToString(); var actualString = actualQueryableMethodExpression.ToString(); Console.WriteLine(); Console.WriteLine("Expected: " + expectedString); Console.WriteLine("Actual: " + actualString); // get the portion of the expected string which represents the 'root'. it will look something like 'q => q.' var parameterString = expectedExpressionPattern.Parameters.Single().ToString(); parameterString = parameterString + " => " + parameterString + "."; expectedString = expectedString.Substring(parameterString.Length); // just verify that the .Where or .OrderBy call matches. We don't verify the root of the tree. Assert.IsTrue(actualString.EndsWith(expectedString)); }
public void FilterCompareSpatialLiterals() { var tests = new[] { new { Operator = "eq", ErrorName = "Equal" }, new { Operator = "ne", ErrorName = "NotEqual" }, new { Operator = "lt", ErrorName = "LessThan" }, new { Operator = "gt", ErrorName = "GreaterThan" }, new { Operator = "le", ErrorName = "LessThanOrEqual" }, new { Operator = "ge", ErrorName = "GreaterThanOrEqual" } }; this.serviceFactory.SetRequestUri("Entities"); foreach (var test in tests) { // spatial literal vs spatial literal this.serviceFactory.SetRequestUri("Entities?$filter=geography'POINT(10 20)' " + test.Operator + " geography'SRID=1234;POINT(10 20)'"); var service = this.serviceFactory.CreateService(); Action processUri = () => RequestUriProcessor.ProcessRequestUri(this.serviceFactory.RequestUri, service, false); processUri.ShouldThrow <DataServiceException>().WithMessage(Microsoft.OData.Core.Strings.MetadataBinder_IncompatibleOperandsError("Edm.GeographyPoint", "Edm.GeographyPoint", test.ErrorName)); } }
public void FilterBySpatialFunctionWithLiterals() { Tuple <string, int>[] testCases = new Tuple <string, int>[] { Tuple.Create("eq 1", 4), Tuple.Create("ne 2", 4), Tuple.Create("gt 2", 0), }; this.serviceFactory.SetRequestUri("Entities"); string resourcePath = this.serviceFactory.RequestUri.OriginalString; foreach (var t in testCases) { this.serviceFactory.ClearQueryArgument(); this.serviceFactory.AddQueryArgument("$filter", "geo.distance(geography'SRID=1234;POINT(20 10)', geography'SRID=1234;POINT(20 10)') " + t.Item1); this.serviceFactory.SetRequestUri(resourcePath + "?$filter=geo.distance(geography'SRID=1234;POINT(20 10)', geography'SRID=1234;POINT(20 10)') " + t.Item1); var service = this.serviceFactory.CreateService(); RequestDescription d = RequestUriProcessor.ProcessRequestUri(this.serviceFactory.RequestUri, service, false); Action <GeographyPoint> verifyPoint = p => { Assert.AreEqual(20.0, p.Longitude); Assert.AreEqual(10.0, p.Latitude); }; RunSpatialDistanceFilterTest(d, verifyPoint, verifyPoint, 1.0, t.Item2); } }
private void SetResourceReferenceToUrl(object entityResource, ResourceProperty navigationProperty, string url) { base.CheckAndIncrementObjectCount(); RequestDescription description = RequestUriProcessor.ProcessRequestUri(RequestUriProcessor.GetAbsoluteUriFromReference(url, base.Service.OperationContext), base.Service, true); if ((this.ContentFormat == ContentFormat.Atom) && !description.IsSingleResult) { if ((navigationProperty != null) && (navigationProperty.Kind == ResourcePropertyKind.ResourceReference)) { throw DataServiceException.CreateBadRequestError(System.Data.Services.Strings.BadRequest_LinkHrefMustReferToSingleResource(navigationProperty.Name)); } } else { object propertyValue = base.Service.GetResource(description, description.SegmentInfos.Length - 1, null); if (navigationProperty.Kind == ResourcePropertyKind.ResourceReference) { base.Updatable.SetReference(entityResource, navigationProperty.Name, propertyValue); } else { WebUtil.CheckResourceExists(propertyValue != null, description.LastSegmentInfo.Identifier); base.Updatable.AddReferenceToCollection(entityResource, navigationProperty.Name, propertyValue); } } }
public void QuerySpatialProperty() { this.serviceFactory.SetRequestUri("Entities(0)/Spatial"); var service = this.serviceFactory.CreateService(); RequestDescription d = RequestUriProcessor.ProcessRequestUri(this.serviceFactory.RequestUri, service, false); Assert.AreEqual(RequestTargetKind.Primitive, d.LastSegmentInfo.TargetKind); Assert.AreEqual("Spatial", d.LastSegmentInfo.Identifier); }
protected object GetTargetResourceToBind(Uri referencedUri, bool checkNull) { System.Data.Services.RequestDescription description = RequestUriProcessor.ProcessRequestUri(referencedUri, this.Service, true); object obj2 = this.Service.GetResource(description, description.SegmentInfos.Length - 1, null); if (checkNull) { WebUtil.CheckResourceExists(obj2 != null, description.LastSegmentInfo.Identifier); } return(obj2); }
[Ignore] // Currently we have overloads of geog, geogPoint; etc. because EF forces us to use properties of type Geography rather than GeographyPoint. public void FilterBySpatialFunctionWrongType() { this.serviceFactory.SetRequestUri("Entities"); this.serviceFactory.AddQueryArgument("$filter", "geo.distance(Spatial, SRID=1234;POINT(10 20)) lt 10"); var service = this.serviceFactory.CreateService(); Action test = () => RequestUriProcessor.ProcessRequestUri(this.serviceFactory.RequestUri, service, false); string expectedFunctions = "geo.distance(System.Data.Spatial.Geography.GeographyPoint, System.Data.Spatial.Geography.GeographyPoint)"; test.ShouldThrow <DataServiceException>().WithMessage(Microsoft.OData.Service.Strings.RequestQueryParser_NoApplicableFunction( "geo.distance", expectedFunctions)); }
public void FilterSpatialMathOperators() { var tests = new[] { new { Operator = "add", ErrorName = "Add" }, new { Operator = "mul", ErrorName = "Multiply" }, }; this.serviceFactory.SetRequestUri("Entities"); foreach (var test in tests) { // property vs spatial literal this.serviceFactory.SetRequestUri("Entities?$filter=Spatial " + test.Operator + " geography'SRID=1234;POINT(10 20)'"); var service = this.serviceFactory.CreateService(); Action processUri = () => RequestUriProcessor.ProcessRequestUri(this.serviceFactory.RequestUri, service, false); processUri.ShouldThrow <DataServiceException>().WithMessage(Microsoft.OData.Core.Strings.MetadataBinder_IncompatibleOperandsError("Edm.Geography", "Edm.GeographyPoint", test.ErrorName)); } }
/// <summary> /// Sets a resource reference to resource referenced by a URL. /// </summary> /// <param name="entityResource">The entity resource to set the resource reference on.</param> /// <param name="navigationProperty">The navigation property for which to set the reference to null.</param> /// <param name="url">The URL which points to the resource to set as the value of the navigation property.</param> private void SetResourceReferenceToUrl(object entityResource, ResourceProperty navigationProperty, string url) { Debug.Assert(entityResource != null, "entityResource != null"); Debug.Assert(navigationProperty != null, "navigationProperty != null"); // Update the object count when you are performing a bind operation. this.CheckAndIncrementObjectCount(); // Get the referenced resource. Uri referencedUri = RequestUriProcessor.GetAbsoluteUriFromReference(url, this.Service.OperationContext); RequestDescription requestDescription = RequestUriProcessor.ProcessRequestUri(referencedUri, this.Service, true /*internalQuery*/); // ATOM deserializer checks that the url doesn't point to a collection. If it does it will ignore the link. if (this.IsAtomRequest && !requestDescription.IsSingleResult) { if (navigationProperty != null && navigationProperty.Kind == ResourcePropertyKind.ResourceReference) { throw DataServiceException.CreateBadRequestError(Microsoft.OData.Service.Strings.BadRequest_LinkHrefMustReferToSingleResource(navigationProperty.Name)); } return; } // Get the resource object referencedResource = this.Service.GetResource(requestDescription, requestDescription.SegmentInfos.Count - 1, null); if (navigationProperty.Kind == ResourcePropertyKind.ResourceReference) { this.Updatable.SetReference(entityResource, navigationProperty.Name, referencedResource); } else { Debug.Assert(navigationProperty.Kind == ResourcePropertyKind.ResourceSetReference, "Only navigation properties are allowed in this method."); // If we are to set the resource to a collection property it must not be null (so check for nulls), otherwise do allow nulls for backward compatibility. WebUtil.CheckResourceExists(referencedResource != null, requestDescription.LastSegmentInfo.Identifier); this.Updatable.AddReferenceToCollection(entityResource, navigationProperty.Name, referencedResource); } }
/// <summary>Applies the information from a link to the specified resource.</summary> /// <param name='link'>LinkDescriptor with information to apply.</param> /// <param name="resourceSet">Set for the target resource.</param> /// <param name='resourceType'>Type for the target resource.</param> /// <param name='resource'>Target resource to which information will be applied.</param> /// <param name="propertyName">Name of the property that this link represents.</param> private void ApplyLink(SyndicationLink link, ResourceSetWrapper resourceSet, ResourceType resourceType, object resource, string propertyName) { Debug.Assert(link != null, "link != null"); Debug.Assert(resourceType != null, "resourceType != null"); Debug.Assert(resource != null, "resource != null"); ResourceProperty property = resourceType.TryResolvePropertyName(propertyName); if (property == null) { // Open navigation properties are not supported on OpenTypes throw DataServiceException.CreateBadRequestError(Strings.OpenNavigationPropertiesNotSupportedOnOpenTypes(propertyName)); } if (property.TypeKind != ResourceTypeKind.EntityType) { throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidNavigationPropertyName(propertyName, resourceType.FullName)); } string typeParameterValue = ValidateTypeParameterForNonOpenTypeProperties(link.MediaType, property); LinkContent linkContent = this.HandleLinkContent(link, resource, resourceSet, resourceType, property, typeParameterValue, propertyName); #region Handle bind/unbind operation // If the href was specified empty or an empty inline element was specified, then we will set the // reference to null - this helps in overrriding if there was a default non-value for this property // else if only link element was specified, and then href points to a single result, then we will // perform a bind operation if ((linkContent == LinkContent.NoInlineElementSpecified && link.Uri != null && String.IsNullOrEmpty(link.Uri.OriginalString)) || linkContent == LinkContent.EmptyInlineElementSpecified) { // update the object count when you are performing a bind operation this.CheckAndIncrementObjectCount(); if (property != null && property.Kind == ResourcePropertyKind.ResourceSetReference) { throw DataServiceException.CreateBadRequestError(Strings.BadRequest_CannotSetCollectionsToNull(propertyName)); } // For open properties, we will assume that this is a reference property and set it to null this.Updatable.SetReference(resource, propertyName, null); } else if (linkContent == LinkContent.NoInlineElementSpecified && link.Uri != null && !String.IsNullOrEmpty(link.Uri.OriginalString)) { // update the object count when you are performing a bind operation this.CheckAndIncrementObjectCount(); // If the link points to a reference navigation property, then update the link Uri referencedUri = RequestUriProcessor.GetAbsoluteUriFromReference(link.Uri.OriginalString, this.Service.OperationContext); RequestDescription description = RequestUriProcessor.ProcessRequestUri(referencedUri, this.Service); if (!description.IsSingleResult) { if (property != null && property.Kind == ResourcePropertyKind.ResourceReference) { throw DataServiceException.CreateBadRequestError(Strings.BadRequest_LinkHrefMustReferToSingleResource(propertyName)); } return; } // no need to check for null. For collection properties, they can never be null and that // check has been added below. For reference properties, if they are null, it means unbind // and hence no need to check for null. // Get the resource object targetResource = this.Service.GetResource(description, description.SegmentInfos.Length - 1, null); if (property.Kind == ResourcePropertyKind.ResourceReference) { this.Updatable.SetReference(resource, propertyName, targetResource); } else { WebUtil.CheckResourceExists(targetResource != null, description.LastSegmentInfo.Identifier); this.Updatable.AddReferenceToCollection(resource, propertyName, targetResource); } } #endregion Handle bind/unbind operation }