VB.NET LINQ string comparison for queries

Mar 7, 2015 at 10:33 PM
Hello,

I was just looking at Raptor and exploring its features and I wanted to try to connect it to an existing application I wrote a few time ago.

That's a VB.NET application and thus I used VB.NET LINQ syntax, like this:

Dim Results = rap.Query(Of QuerySchema)(Function(x) x.StringValue = "MyString")

Raptor was generating an exception with that query while other queries with other kind of parameters were ok. I knew that this could be a problem with VB.NET LINQ as I had problems with other software.

The problem about comparison of strings in VB.NET LINQ is explained in this thread:

http://stackoverflow.com/questions/12194855/implementing-string-comparer-in-custom-linq-provider-in-vb

I tried to code a quick hack to understand if I could solve the problem so here are the changes I made to make it working:
        protected override Expression VisitBinary(BinaryExpression b)
        {
            this.Visit(b.Left);
            ExpressionType t = b.NodeType;

            // Netcore
            // VisualBasic.NET hack to support equal (=) comparator for strings

            if (b.Left is MethodCallExpression) {
                // Cast 
                var method = (MethodCallExpression)b.Left;
                // String checking avoids adding dependency on Microsoft.VisualBasic DLL
                if (method.Method.DeclaringType.FullName.Equals ("Microsoft.VisualBasic.CompilerServices.Operators") && method.Method.Name=="CompareString") {
                    var left = method.Arguments[0];
                    // Removes dot if any
                    var leftStr = left.ToString().Substring(left.ToString().IndexOf('.') + 1);
                    var right = method.Arguments[1].ToString().Replace("\"", String.Empty);
                    RDBExpression exp = RDBExpression.Equal;
                    _bitmap.Push(qexpression("" + leftStr, exp, right));

                    return (b);
                }

            }

            if (t == ExpressionType.Equal || t== ExpressionType.NotEqual || 
                t == ExpressionType.LessThan || t == ExpressionType.LessThanOrEqual ||
                t == ExpressionType.GreaterThan || t == ExpressionType.GreaterThanOrEqual)
                _stack.Push(b.NodeType);


            this.Visit(b.Right);
            t = b.NodeType;
            if (t == ExpressionType.Equal || t == ExpressionType.NotEqual ||
                t == ExpressionType.LessThanOrEqual || t == ExpressionType.LessThan ||
                t == ExpressionType.GreaterThanOrEqual || t == ExpressionType.GreaterThan
                )
            {
                // binary expression 
                object lv = _stack.Pop();
                ExpressionType lo = (ExpressionType)_stack.Pop();
                object ln = _stack.Pop();
                RDBExpression exp = RDBExpression.Equal;
                // FEATURE : add contains , between, startswith
                if (lo == ExpressionType.LessThan) exp = RDBExpression.Less;
                else if (lo == ExpressionType.LessThanOrEqual) exp = RDBExpression.LessEqual;
                else if (lo == ExpressionType.GreaterThan) exp = RDBExpression.Greater;
                else if (lo == ExpressionType.GreaterThanOrEqual) exp = RDBExpression.GreaterEqual;
                else if (lo == ExpressionType.NotEqual) exp = RDBExpression.NotEqual;

                _bitmap.Push(qexpression("" + ln, exp, lv));
            }

            if (t == ExpressionType.And || t == ExpressionType.AndAlso ||
                t == ExpressionType.Or || t == ExpressionType.OrElse)
            {
                if (_bitmap.Count > 1)
                {
                    // do bitmap operations 
                    WAHBitArray r = (WAHBitArray)_bitmap.Pop();
                    WAHBitArray l = (WAHBitArray)_bitmap.Pop();

                    if (t == ExpressionType.And || t == ExpressionType.AndAlso)
                        _bitmap.Push(r.And(l));
                    if (t == ExpressionType.Or || t == ExpressionType.OrElse)
                        _bitmap.Push(r.Or(l));
                }
                else
                {
                    // single bitmap operation
                }
            }
            return b;
        }
There's probably a bug with these changes because I think that returning so early in that method would remove support for boolean operators so the method itself should be refactored to support those changes. However, I hope this is a good start for a fix

I'm sure there aren't many VB.NET lovers out there but I guess that fixing that problem would be good.

I used a string comparison for DeclaringType to avoid adding a dependency on Microsoft.VisualBasic DLL.

Hope this help.
Mar 8, 2015 at 6:59 AM
Thanks I will look into it.
Mar 8, 2015 at 11:23 AM
Fixed now in v3.2.9
Mar 8, 2015 at 12:42 PM
Brilliant. Thanks !