Skip to content

Commit

Permalink
Dynamic property support in filter expressions (#1346)
Browse files Browse the repository at this point in the history
  • Loading branch information
gathogojr authored Nov 13, 2024
1 parent 2b82a2e commit 14bd2b2
Show file tree
Hide file tree
Showing 17 changed files with 2,751 additions and 58 deletions.
130 changes: 128 additions & 2 deletions src/Microsoft.AspNetCore.OData/Microsoft.AspNetCore.OData.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7735,6 +7735,11 @@
Looks up a localized string similar to The type '{0}' must be an enum or Nullable<T> where T is an enum type..
</summary>
</member>
<member name="P:Microsoft.AspNetCore.OData.SRResources.TypeMustBeOpenType">
<summary>
Looks up a localized string similar to The type &apos;{0}&apos; must be an open type. The dynamic properties container property is only expected on open types..
</summary>
</member>
<member name="P:Microsoft.AspNetCore.OData.SRResources.TypeMustBeRelated">
<summary>
Looks up a localized string similar to The type &apos;{0}&apos; does not inherit from and is not a base type of &apos;{1}&apos;..
Expand Down Expand Up @@ -8705,7 +8710,7 @@
</member>
<member name="M:Microsoft.AspNetCore.OData.Query.EnableQueryAttribute.GetODataQueryContext(System.Object,System.Linq.IQueryable,Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor,Microsoft.AspNetCore.Http.HttpRequest)">
<summary>
Get the ODaya query context.
Get the OData query context.
</summary>
<param name="responseValue">The response value.</param>
<param name="singleResultCollection">The content as SingleResult.Queryable.</param>
Expand Down Expand Up @@ -9268,6 +9273,15 @@
<param name="context">The query binder context.</param>
<returns>The LINQ <see cref="T:System.Linq.Expressions.Expression"/> created.</returns>
</member>
<member name="M:Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.BindCollectionOpenPropertyAccessNode(Microsoft.OData.UriParser.CollectionOpenPropertyAccessNode,Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext)">
<summary>
Binds a <see cref="T:Microsoft.OData.UriParser.CollectionPropertyAccessNode"/> to create a LINQ <see cref="T:System.Linq.Expressions.Expression"/> that
represents the semantics of the <see cref="T:Microsoft.OData.UriParser.CollectionPropertyAccessNode"/>.
</summary>
<param name="openCollectionNode">The query node to bind.</param>
<param name="context">The query binder context.</param>
<returns>The LINQ <see cref="T:System.Linq.Expressions.Expression"/> created.</returns>
</member>
<member name="M:Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.BindDynamicPropertyAccessQueryNode(Microsoft.OData.UriParser.SingleValueOpenPropertyAccessNode,Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext)">
<summary>
Binds a <see cref="T:Microsoft.OData.UriParser.SingleValueOpenPropertyAccessNode"/> to create a LINQ <see cref="T:System.Linq.Expressions.Expression"/> that
Expand Down Expand Up @@ -9433,7 +9447,15 @@
<summary>
Gets property for dynamic properties dictionary.
</summary>
<param name="openNode"></param>
<param name="openNode">The single-valued open property access node.</param>
<param name="context">The query binder context.</param>
<returns>Returns CLR property for dynamic properties container.</returns>
</member>
<member name="M:Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.GetDynamicPropertyContainer(Microsoft.OData.UriParser.CollectionOpenPropertyAccessNode,Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext)">
<summary>
Gets property for dynamic properties dictionary.
</summary>
<param name="openCollectionNode">The collection-valued open property access node.</param>
<param name="context">The query binder context.</param>
<returns>Returns CLR property for dynamic properties container.</returns>
</member>
Expand All @@ -9445,6 +9467,24 @@
<param name="context">The query binder context.</param>
<returns>Returns null if no aggregations were used so far</returns>
</member>
<member name="M:Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.BindPropertyAccessExpression(Microsoft.OData.UriParser.SingleValueNode,System.Reflection.PropertyInfo,Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext)">
<summary>
Binds property to the source node.
</summary>
<param name="sourceNode">The source node.</param>
<param name="prop">The property.</param>
<param name="context">The query binder context.</param>
<returns>The LINQ <see cref="T:System.Linq.Expressions.Expression"/> created.</returns>
</member>
<member name="M:Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.GetDynamicPropertyContainer(Microsoft.OData.Edm.IEdmTypeReference,Microsoft.OData.UriParser.QueryNodeKind,Microsoft.OData.Edm.IEdmModel)">
<summary>
Gets property for dynamic properties dictionary.
</summary>
<param name="edmTypeReference">The Edm type reference.</param>
<param name="queryNodeKind">Query node kind.</param>
<param name="model">The Edm model.</param>
<returns>Returns CLR property for dynamic properties container.</returns>
</member>
<member name="M:Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.ApplyNullPropagationForFilterBody(System.Linq.Expressions.Expression,Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext)">
<summary>
Apply null propagation for filter body.
Expand All @@ -9453,6 +9493,92 @@
<param name="context">The query binder context.</param>
<returns>The LINQ <see cref="T:System.Linq.Expressions.Expression"/> created.</returns>
</member>
<member name="M:Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.BindDynamicPropertyAccessExpression(Microsoft.OData.UriParser.SingleValueOpenPropertyAccessNode,Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext)">
<summary>
Binds dynamic property to the source node.
</summary>
<param name="openNode">The query node to bind.</param>
<param name="context">The query binder context.</param>
<returns>The LINQ <see cref="T:System.Linq.Expressions.Expression"/> created.</returns>
</member>
<member name="M:Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.CreateDynamicPropertyAccessExpression(System.Linq.Expressions.Expression,System.String,Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext)">
<summary>
Creates an expression for retrieving a dynamic property from the container property.
</summary>
<param name="containerPropertyAccessExpr">The container property access expression.</param>
<param name="propertyName">The dynamic property name.</param>
<param name="context">The query binder context.</param>
<returns>The LINQ <see cref="T:System.Linq.Expressions.Expression"/> created.</returns>
</member>
<member name="M:Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.BindNestedDynamicPropertyAccessExpression(Microsoft.OData.UriParser.SingleValueOpenPropertyAccessNode,Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext)">
<summary>
Binds nested dynamic property to the source node.
</summary>
<param name="openNode">The query node to bind.</param>
<param name="context">The query binder context.</param>
<returns>The LINQ <see cref="T:System.Linq.Expressions.Expression"/> created.</returns>
</member>
<member name="M:Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.CreateNestedDynamicPropertyAccessExpression(System.Linq.Expressions.Expression,Microsoft.OData.UriParser.SingleValueOpenPropertyAccessNode,Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext)">
<summary>
Creates an expression for retrieving a nested dynamic property.
</summary>
<param name="sourceExpr">The source expression.</param>
<param name="openNode">The query node to bind.</param>
<param name="context">The query binder context.</param>
<returns>The LINQ <see cref="T:System.Linq.Expressions.Expression"/> created.</returns>
</member>
<member name="M:Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.BindCollectionOpenPropertyAccessExpression(Microsoft.OData.UriParser.CollectionOpenPropertyAccessNode,Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext)">
<summary>
Binds dynamic collection property to the source node.
</summary>
<param name="openCollectionNode">The query node to bind.</param>
<param name="context">The query binder context.</param>
<returns>The LINQ <see cref="T:System.Linq.Expressions.Expression"/> created.</returns>
</member>
<member name="M:Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.BindNestedCollectionOpenPropertyAccessExpression(Microsoft.OData.UriParser.CollectionOpenPropertyAccessNode,Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext)">
<summary>
Binds nested dynamic collection property to the source node.
</summary>
<param name="openCollectionNode">The query node to bind.</param>
<param name="context">The query binder context.</param>
<returns>The LINQ <see cref="T:System.Linq.Expressions.Expression"/> created.</returns>
</member>
<member name="M:Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.CreateNestedCollectionOpenPropertyAccessExpression(System.Linq.Expressions.Expression,Microsoft.OData.UriParser.CollectionOpenPropertyAccessNode,Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext)">
<summary>
Creates an expression for retrieving a nested dynamic collection property.
</summary>
<param name="sourceExpr">The source expression.</param>
<param name="openCollectionNode">The query node to bind.</param>
<param name="context">The query binder context.</param>
<returns>The LINQ <see cref="T:System.Linq.Expressions.Expression"/> created.</returns>
</member>
<member name="M:Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.CreateNestedDynamicPropertyAccessExpression(System.Linq.Expressions.Expression,System.String,Microsoft.OData.UriParser.QueryNodeKind,Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext)">
<summary>
Creates an expression for retrieving a dynamic property from the container property.
</summary>
<param name="sourceExpr">The source expression.</param>
<param name="propertyName">The property name.</param>
<param name="queryNodeKind">The query node kind.</param>
<param name="context">The query binder context.</param>
<returns>The LINQ <see cref="T:System.Linq.Expressions.Expression"/> created.</returns>
</member>
<member name="M:Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.CreateResourceTypeNotInModelExceptionExpression(System.Linq.Expressions.Expression)">
<summary>
Creates an <see cref="T:Microsoft.OData.ODataException"/> for the scenario where resource type is not in the Edm model.
</summary>
<param name="instanceTypeExpr">The resource instance type expression.</param>
<returns>The LINQ <see cref="T:System.Linq.Expressions.Expression"/> created.</returns>
</member>
<member name="M:Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.CreatePropertyIsNotCollectionExceptionExpression(System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.String)">
<summary>
Creates an <see cref="T:Microsoft.OData.ODataException"/> for the scenario where
any/any operators are applied to a property that is not a collection.
</summary>
<param name="instanceTypeExpr">The resource instance type expression.</param>
<param name="propertyTypeExpr">The property type expression.</param>
<param name="propertyName">The property name.</param>
<returns>The LINQ <see cref="T:System.Linq.Expressions.Expression"/> created.</returns>
</member>
<member name="M:Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.BindSingleValueFunctionCallNode(Microsoft.OData.UriParser.SingleValueFunctionCallNode,Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext)">
<summary>
Binds a <see cref="T:Microsoft.OData.UriParser.SingleValueFunctionCallNode"/> to create a LINQ <see cref="T:System.Linq.Expressions.Expression"/> that
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/Microsoft.AspNetCore.OData/Properties/SRResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -745,4 +745,7 @@
<value>Unable to identify a unique property named '{0}'.</value>
<comment>{0} = Property Name</comment>
</data>
<data name="TypeMustBeOpenType" xml:space="preserve">
<value>The type '{0}' must be an open type. The dynamic properties container property is only expected on open types.</value>
</data>
</root>
2 changes: 2 additions & 0 deletions src/Microsoft.AspNetCore.OData/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1759,6 +1759,7 @@ static Microsoft.AspNetCore.OData.Query.Expressions.BinderExtensions.ApplyBind(t
static Microsoft.AspNetCore.OData.Query.Expressions.BinderExtensions.ApplyBind(this Microsoft.AspNetCore.OData.Query.Expressions.ISelectExpandBinder binder, object source, Microsoft.OData.UriParser.SelectExpandClause selectExpandClause, Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext context) -> object
static Microsoft.AspNetCore.OData.Query.Expressions.BinderExtensions.ApplyBind(this Microsoft.AspNetCore.OData.Query.Expressions.ISelectExpandBinder binder, System.Linq.IQueryable source, Microsoft.OData.UriParser.SelectExpandClause selectExpandClause, Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext context) -> System.Linq.IQueryable
static Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.ApplyNullPropagationForFilterBody(System.Linq.Expressions.Expression body, Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext context) -> System.Linq.Expressions.Expression
static Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.GetDynamicPropertyContainer(Microsoft.OData.UriParser.CollectionOpenPropertyAccessNode openCollectionNode, Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext context) -> System.Reflection.PropertyInfo
static Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.GetDynamicPropertyContainer(Microsoft.OData.UriParser.SingleValueOpenPropertyAccessNode openNode, Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext context) -> System.Reflection.PropertyInfo
static Microsoft.AspNetCore.OData.Query.HttpRequestODataQueryExtensions.GetETag(this Microsoft.AspNetCore.Http.HttpRequest request, Microsoft.Net.Http.Headers.EntityTagHeaderValue entityTagHeaderValue) -> Microsoft.AspNetCore.OData.Query.ETag
static Microsoft.AspNetCore.OData.Query.HttpRequestODataQueryExtensions.GetETag<TEntity>(this Microsoft.AspNetCore.Http.HttpRequest request, Microsoft.Net.Http.Headers.EntityTagHeaderValue entityTagHeaderValue) -> Microsoft.AspNetCore.OData.Query.ETag<TEntity>
Expand Down Expand Up @@ -1883,6 +1884,7 @@ virtual Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.BindCeiling(Mic
virtual Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.BindCollectionComplexNode(Microsoft.OData.UriParser.CollectionComplexNode collectionComplexNode, Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext context) -> System.Linq.Expressions.Expression
virtual Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.BindCollectionConstantNode(Microsoft.OData.UriParser.CollectionConstantNode node, Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext context) -> System.Linq.Expressions.Expression
virtual Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.BindCollectionNode(Microsoft.OData.UriParser.CollectionNode node, Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext context) -> System.Linq.Expressions.Expression
virtual Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.BindCollectionOpenPropertyAccessNode(Microsoft.OData.UriParser.CollectionOpenPropertyAccessNode openCollectionNode, Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext context) -> System.Linq.Expressions.Expression
virtual Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.BindCollectionPropertyAccessNode(Microsoft.OData.UriParser.CollectionPropertyAccessNode propertyAccessNode, Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext context) -> System.Linq.Expressions.Expression
virtual Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.BindCollectionResourceCastNode(Microsoft.OData.UriParser.CollectionResourceCastNode node, Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext context) -> System.Linq.Expressions.Expression
virtual Microsoft.AspNetCore.OData.Query.Expressions.QueryBinder.BindConcat(Microsoft.OData.UriParser.SingleValueFunctionCallNode node, Microsoft.AspNetCore.OData.Query.Expressions.QueryBinderContext context) -> System.Linq.Expressions.Expression
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public static Expression CreateBinaryExpression(BinaryOperatorKind binaryOperato
left = CreateDateBinaryExpression(left, querySettings);
right = CreateDateBinaryExpression(right, querySettings);
}
else if((IsType<TimeOnly>(leftUnderlyingType) && IsTimeOfDay(rightUnderlyingType)) ||
else if ((IsType<TimeOnly>(leftUnderlyingType) && IsTimeOfDay(rightUnderlyingType)) ||
(IsTimeOfDay(leftUnderlyingType) && IsType<TimeOnly>(rightUnderlyingType)))
{
left = CreateTimeBinaryExpression(left, querySettings);
Expand Down Expand Up @@ -665,14 +665,14 @@ public static Expression DateTimeOffsetToDateTime(Expression expression, TimeZon
var dto = parameterizedConstantValue as DateTimeOffset?;
if (dto != null)
{
if (settings.EnableConstantParameterization)
{
return LinqParameterContainer.Parameterize(typeof(DateTime), EdmPrimitiveHelper.ConvertPrimitiveValue(dto.Value, typeof(DateTime), timeZoneInfo));
}
else
{
return Expression.Constant(EdmPrimitiveHelper.ConvertPrimitiveValue(dto.Value, typeof(DateTime), timeZoneInfo), typeof(DateTime));
}
if (settings.EnableConstantParameterization)
{
return LinqParameterContainer.Parameterize(typeof(DateTime), EdmPrimitiveHelper.ConvertPrimitiveValue(dto.Value, typeof(DateTime), timeZoneInfo));
}
else
{
return Expression.Constant(EdmPrimitiveHelper.ConvertPrimitiveValue(dto.Value, typeof(DateTime), timeZoneInfo), typeof(DateTime));
}
}
return expression;
}
Expand Down
Loading

0 comments on commit 14bd2b2

Please sign in to comment.