diff --git a/F23.ODataLite/F23.ODataLite.csproj b/F23.ODataLite/F23.ODataLite.csproj
index 818cd15..c15fea8 100644
--- a/F23.ODataLite/F23.ODataLite.csproj
+++ b/F23.ODataLite/F23.ODataLite.csproj
@@ -12,7 +12,7 @@
odata asp.net core lite
MIT
2019, feature[23]
- 2.0.0-beta1
+ 2.0.0-beta2
diff --git a/F23.ODataLite/Internal/ExpressionQueryTokenVisitor.cs b/F23.ODataLite/Internal/ExpressionQueryTokenVisitor.cs
index d53a4a1..94e5d35 100644
--- a/F23.ODataLite/Internal/ExpressionQueryTokenVisitor.cs
+++ b/F23.ODataLite/Internal/ExpressionQueryTokenVisitor.cs
@@ -11,15 +11,18 @@ namespace F23.ODataLite.Internal
internal class ExpressionQueryTokenVisitor : ISyntacticTreeVisitor
{
private static readonly MethodInfo _hasFlagMethod = typeof(Enum).GetMethod(nameof(Enum.HasFlag), BindingFlags.Instance | BindingFlags.Public);
+ private static readonly MethodInfo _toStringMethod = typeof(object).GetMethod(nameof(ToString), BindingFlags.Instance | BindingFlags.Public);
private static readonly MethodInfo _fuzzyEqualsMethod = typeof(ExpressionQueryTokenVisitor).GetMethod(nameof(FuzzyEquals), BindingFlags.Static | BindingFlags.NonPublic);
private readonly ParameterExpression _parameter;
private readonly IEnumerable _properties;
+ private readonly bool _inMemoryEvaluation;
- public ExpressionQueryTokenVisitor(ParameterExpression parameterExpression, IEnumerable properties)
+ public ExpressionQueryTokenVisitor(ParameterExpression parameterExpression, IEnumerable properties, bool inMemoryEvaluation)
{
_parameter = parameterExpression;
_properties = properties;
+ _inMemoryEvaluation = inMemoryEvaluation;
}
private static bool FuzzyEquals(object left, object right)
@@ -77,7 +80,21 @@ public Expression Visit(BinaryOperatorToken tokenIn)
private Expression GetEqualsExpression(BinaryOperatorToken tokenIn)
{
- return Expression.Call(null, _fuzzyEqualsMethod, Expression.Convert(tokenIn.Left.Accept(this), typeof(object)), Expression.Convert(tokenIn.Right.Accept(this), typeof(object)));
+ if (_inMemoryEvaluation)
+ return Expression.Call(null, _fuzzyEqualsMethod, Expression.Convert(tokenIn.Left.Accept(this), typeof(object)), Expression.Convert(tokenIn.Right.Accept(this), typeof(object)));
+
+ var left = tokenIn.Left.Accept(this);
+ var right = tokenIn.Right.Accept(this);
+
+ return Expression.Or(
+ Expression.Equal(left, right),
+ Expression.And(
+ Expression.And(
+ Expression.NotEqual(left, Expression.Constant(null)),
+ Expression.NotEqual(right, Expression.Constant(null))),
+ Expression.Equal(Expression.Call(left, _toStringMethod), Expression.Call(right, _toStringMethod))
+ )
+ );
}
public Expression Visit(InToken tokenIn)
diff --git a/F23.ODataLite/Internal/ODataFilterOperator.cs b/F23.ODataLite/Internal/ODataFilterOperator.cs
index d36097e..5d914c2 100644
--- a/F23.ODataLite/Internal/ODataFilterOperator.cs
+++ b/F23.ODataLite/Internal/ODataFilterOperator.cs
@@ -9,7 +9,7 @@ namespace F23.ODataLite.Internal
{
internal static class ODataFilterOperator
{
- public static IQueryable Apply(IQueryable data, IEnumerable properties, string parameter)
+ public static IQueryable Apply(IQueryable data, IEnumerable properties, string parameter, bool isQueryable)
{
var parser = new UriQueryExpressionParser(10);
@@ -17,7 +17,7 @@ public static IQueryable Apply(IQueryable data, IEnumerable or IEnumerable to use ODataLite. Pass a queryable or enumerable, or remove this attribute.");
+ if (ok.Value is HypermediaResponse hypermedia)
+ {
+ isQueryable = hypermedia.Content.IsQueryable(out rawData);
+
+ if (!isQueryable && !hypermedia.Content.IsEnumerable(out rawData))
+ {
+ throw new InvalidOperationException("HypermediaResponse.Content must be IQueryable or IEnumerable to use ODataLite. Pass a queryable or enumerable, or remove this attribute.");
+ }
+ }
+ else
+ {
+ throw new InvalidOperationException("Data must be IQueryable or IEnumerable to use ODataLite. Pass a queryable or enumerable, or remove this attribute.");
+ }
}
var itemType = rawData.GetType().GetGenericArguments().First();
@@ -55,7 +68,7 @@ public override async Task OnResultExecutionAsync(ResultExecutingContext context
applyMethod = applyMethod.MakeGenericMethod(itemType);
- if (applyMethod.Invoke(null, new object[] { context, rawData, ok.Value as HypermediaResponse }) is Task result)
+ if (applyMethod.Invoke(null, new object[] { context, rawData, ok.Value as HypermediaResponse, isQueryable }) is Task result)
{
context.Result = await result;
}
@@ -63,7 +76,7 @@ public override async Task OnResultExecutionAsync(ResultExecutingContext context
await base.OnResultExecutionAsync(context, next);
}
- private static async Task ApplyODataAsync(ActionContext context, IQueryable rawData, HypermediaResponse hypermediaResponse)
+ private static async Task ApplyODataAsync(ActionContext context, IQueryable rawData, HypermediaResponse hypermediaResponse, bool isQueryable)
{
var data = (IQueryable)rawData;
@@ -74,7 +87,7 @@ private static async Task ApplyODataAsync(ActionContext context
if (query.HasParam("$filter", out var filterValue))
{
- data = ODataFilterOperator.Apply(data, properties.Value, filterValue);
+ data = ODataFilterOperator.Apply(data, properties.Value, filterValue, isQueryable);
}
if (query.HasParam("$orderby", out var orderByValue))