Where clause can't be converted to predicate expression

Posts   
 
    
GabeNodland avatar
Posts: 65
Joined: 31-Dec-2004
# Posted on: 11-Jun-2008 18:32:11   

llbl=2.6, sqlServer=2007, targetLanguate=vb.net, templateGroup=adapter, .net=3.5

Hello, I am really excited about the new release and I am trying to get started testing so we can convert everything over. I ran into this error and I figure I must be doing something wrong here.

I get the following error: The binary expression '(CompareString([508], "123 Main Street", False) = 0)' can't be converted to a predicate expression.

when I run this code:



        Dim adapter As New LMTEST.LLBL.DatabaseSpecific.DataAccessAdapter
        Dim meta As New LMTEST.LLBL.Linq.LinqMetaData(adapter)

        Dim q = From s In meta.Shipment _
                Where s.Address = "123 Main Street" _
                Select s

        'Error happens on next line
        For Each row In q
            Console.WriteLine(row.Address)
        Next


I must be doing something wrong here when working with linq and strings, it works when I change it to

        Dim q = From s In meta.Shipment _
                Where s.ShipmentID = 1 _
                Select s

The Shipment Entity's Address Field is type System.String not a Nullable(Of String)

It also worked when i tried the same thing in c# using my vb.net generated code.

this code worked fine:


        var q = from s in meta.Shipment 
                where s.Address == "123 Main Street" 
                select s;

here is the stack trace:

" at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder. HandleBinaryExpressionSeparateOperands(BinaryExpression expressionToHandle, Expression leftSide, Expression rightSide) at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder. HandleBinaryExpressionBooleanOperator(BinaryExpression expressionToHandle) at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle) at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder. HandleExpression(Expression expressionToHandle) at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder. HandleLambdaExpression(LambdaExpression expressionToHandle) at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle) at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleExpression(Expression expressionToHandle) at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder. HandleWhereExpression(WhereExpression expressionToHandle) at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression(Expression expressionToHandle) at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleExpression(Expression expressionToHandle) at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler. HandleSelectExpression(SelectExpression expressionToHandle, SelectExpression newInstance) at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleSelectExpression( SelectExpression expressionToHandle) at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleSelectExpression( SelectExpression expressionToHandle) at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.GenericExpressionHandler.HandleExpression( Expression expressionToHandle) at SD.LLBLGen.Pro.LinqSupportClasses.ExpressionHandlers.QueryExpressionBuilder.HandleExpression( Expression expressionToHandle) at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.HandleExpressionTree(Expression expression) at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.Execute(Expression expression) at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.System.Linq.IQueryProvider.Execute(Expression expression) at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProQuery1.Execute() at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProQuery1.System.Collections.Generic.IEnumerable<T>. GetEnumerator() at ConsoleApplication1.Module1.Main() in C:\Projects\LLBL26test\ConsoleApplication1\Module1.vb:line 12 at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart()"

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 11-Jun-2008 19:22:39   

I think this is caused by a VB.NET specific thing. The VB.NET compiler creates different expression trees sometimes, but it's unknown when it generates which differences compared to the C# compiler (yes, MS did a lousy job in that department), so these issues are unfortunately hard to track down.

We wrote everything with C#, and then tried a lot of edge things in VB.NET as well, where we thought it might be different. Obviously we skipped the most simple one of all, the one you ran into simple_smile

It seems it calls a CompareString() function, very strange. I'll try to reproduce it and fix it.

I think Where s.Address.Equals("123 Main Street") should work in VB.NET though.

Expect a fix thursday.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 12-Jun-2008 11:55:20   

Equals indeed works, '=' doesn't, because the VB compiler doesn't create a simple BinaryExpression with an 'Equal' operator, or with an op_equals method call, but it generates a CompareString() method call. disappointed

There are three areas which are problematic, according to the linq to sql sourcecode (sorry MS, but you should document this better).

1) stringfield = stringvalue -> will result in Microsoft.VisualBasic.CompilerServices.Operators.CompareString call. The documentation of this method says: 'returns 0 if strings do NOT match', however the tree compares the result with 0, and should be equal if the strings match... testing it with linq to sql suggests the documentation is wrong. 2) the LIKE operator in VB (I don't know what that does, will find out) 3) some conversion routines (I suspect CInt() and the like)

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 12-Jun-2008 13:02:58   

Ok: - CompareString() -> fixed in next build. - LikeString() etc. (VB.NET Like operator) -> not supported, one should use .StartsWith(), .EndsWith() or .Contains() to produce LIKE queries. A proper exception is now thrown - CInt() etc. are now detected and converted to proper ConvertExpressions.

Available in next build.

Frans Bouma | Lead developer LLBLGen Pro