Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] ParseException: Operator '==' incompatible with operand types 'ObjectId' and 'ObjectId' #94

Closed
aveyrier opened this issue Jun 30, 2017 · 4 comments
Assignees
Labels

Comments

@aveyrier
Copy link

When using this library with the MongoDB.Driver package, an error occurs with the DynamicExpressionParser.ParseLambda method while trying to compare an object containing an ObjectId property with another ObjectId object.

This kind of comparison works fine inside a classic lambda expression (e.g. entity => entity.Id == ObjectId.Parse(id)) but it throws with the dynamic equivalent (e.g. "it.Id == @0"). Other operators doesn't work neither (>, <, >=, <=, !=) even though they are defined in the struct, but the Equals method works fine.

Code

private async Task<Todo> GetTodo(string id)
{
    ParameterExpression[] parameters = new[]
    {
        Expression.Parameter(typeof(Todo), "it"),
    };

    LambdaExpression find = DynamicExpressionParser.ParseLambda(parameters, typeof(bool), "it.Id == @0", ObjectId.Parse(id));

    return await _db.GetCollection<Todo>("Todos")
        .Find((Expression<Func<Todo, bool>>)find)
        .Limit(1)
        .SingleOrDefaultAsync();
}

Error

ParseException: Operator '==' incompatible with operand types 'ObjectId' and 'ObjectId'

Stacktrace

System.Linq.Dynamic.Core.ExpressionParser.CheckAndPromoteOperands(Type signatures, string opName, ref Expression left, ref Expression right, int errorPos)
System.Linq.Dynamic.Core.ExpressionParser.ParseComparisonOperator()
System.Linq.Dynamic.Core.ExpressionParser.ParseLogicalAndOrOperator()
System.Linq.Dynamic.Core.ExpressionParser.ParseIn()
System.Linq.Dynamic.Core.ExpressionParser.ParseAndOperator()
System.Linq.Dynamic.Core.ExpressionParser.ParseOrOperator()
System.Linq.Dynamic.Core.ExpressionParser.ParseLambdaOperator()
System.Linq.Dynamic.Core.ExpressionParser.ParseNullCoalescingOperator()
System.Linq.Dynamic.Core.ExpressionParser.ParseConditionalOperator()
System.Linq.Dynamic.Core.ExpressionParser.Parse(Type resultType, bool createParameterCtor)
System.Linq.Dynamic.Core.DynamicExpressionParser.ParseLambda(bool createParameterCtor, ParameterExpression[] parameters, Type resultType, string expression, Object[] values)
System.Linq.Dynamic.Core.DynamicExpressionParser.ParseLambda(ParameterExpression[] parameters, Type resultType, string expression, Object[] values)
TodoList.Controllers.TodosController+<GetEntity>d__4.MoveNext() in TodosController.cs
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()
TodoList.Controllers.TodosController+<Get>d__3.MoveNext() in TodosController.cs
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeActionMethodAsync>d__27.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeNextActionFilterAsync>d__25.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeNextResourceFilter>d__22.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ResourceExecutedContext context)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(ref State next, ref Scope scope, ref object state, ref bool isCompleted)
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeAsync>d__20.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Builder.RouterMiddleware+<Invoke>d__4.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware+<Invoke>d__7.MoveNext()
@StefH
Copy link
Collaborator

StefH commented Jul 1, 2017

Maybe when that ObjectId property implements the interface IComparable it can work ?
See https://msdn.microsoft.com/en-us/library/system.icomparable(v=vs.110).aspx

Else can you provide the full class from ObjectId ?

@StefH StefH self-assigned this Jul 1, 2017
@StefH StefH added the question label Jul 1, 2017
@StefH StefH changed the title ParseException: Operator '==' incompatible with operand types 'ObjectId' and 'ObjectId' [Question] ParseException: Operator '==' incompatible with operand types 'ObjectId' and 'ObjectId' Jul 1, 2017
@aveyrier
Copy link
Author

aveyrier commented Jul 2, 2017

ObjectId implements the interface IComparable<ObjectId>. You can see below the full class (or you can see it here if you want the full implementation : https://github.com/mongodb/mongo-csharp-driver/blob/master/src/MongoDB.Bson/ObjectModel/ObjectId.cs).

public struct ObjectId : IComparable<ObjectId>, IEquatable<ObjectId>, IConvertible
{
    public ObjectId(byte[] bytes);
    public ObjectId(string value);
    public ObjectId(DateTime timestamp, int machine, short pid, int increment);
    public ObjectId(int timestamp, int machine, short pid, int increment);

    public static ObjectId Empty { get; }
    public short Pid { get; }
    public int Machine { get; }
    public int Timestamp { get; }
    public int Increment { get; }
    public DateTime CreationTime { get; }

    public static ObjectId GenerateNewId();
    public static ObjectId GenerateNewId(DateTime timestamp);
    public static ObjectId GenerateNewId(int timestamp);
    public static byte[] Pack(int timestamp, int machine, short pid, int increment);
    public static ObjectId Parse(string s);
    public static bool TryParse(string s, out ObjectId objectId);
    public static void Unpack(byte[] bytes, out int timestamp, out int machine, out short pid, out int increment);
    public int CompareTo(ObjectId other);
    public bool Equals(ObjectId rhs);
    public override bool Equals(object obj);
    public override int GetHashCode();
    public byte[] ToByteArray();
    public void ToByteArray(byte[] destination, int offset);
    public override string ToString();

    public static bool operator ==(ObjectId lhs, ObjectId rhs);
    public static bool operator !=(ObjectId lhs, ObjectId rhs);
    public static bool operator <(ObjectId lhs, ObjectId rhs);
    public static bool operator >(ObjectId lhs, ObjectId rhs);
    public static bool operator <=(ObjectId lhs, ObjectId rhs);
    public static bool operator >=(ObjectId lhs, ObjectId rhs);
}

@StefH
Copy link
Collaborator

StefH commented Jul 3, 2017

I will take a look.

@StefH StefH changed the title [Question] ParseException: Operator '==' incompatible with operand types 'ObjectId' and 'ObjectId' [Bug] ParseException: Operator '==' incompatible with operand types 'ObjectId' and 'ObjectId' Jul 8, 2017
@StefH StefH added the bug label Jul 8, 2017
StefH added a commit that referenced this issue Jul 8, 2017
@StefH StefH closed this as completed Jul 8, 2017
@StefH StefH removed the question label Nov 19, 2019
@loob91
Copy link

loob91 commented May 4, 2020

Are you sure this is closed ?

When I use this code :
var _expression = DynamicExpressionParser.ParseLambda<T, bool>(ParsingConfig.Default, false, _filterString, eavcustomattributes.id, _value.ToString());

Result is :
Param_1.value == 12/01/2017 00:00:00

And then I have the error :
Operator '==' incompatible with operand types 'DateTime?' and 'Int32'

I can understand it because there is no escape character for the date. Or maybe there is something I'm missing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

3 participants