What kind of query is that!

Posts   
 
    
simmotech
User
Posts: 1024
Joined: 01-Feb-2006
# Posted on: 25-Apr-2019 15:24:42   

I've just changed a column from being nvarchar(32) to binary(20)

And this query now completely fails:-

                    var existingImage = adapter.FetchFirst(new QueryFactory().Image
                        .Where(ImageFields.Hash == coverImage.Hash)
                        .Where(ImageFields.Data.Length().Equal(bytes.Length)));

This is the Exception

SD.LLBLGen.Pro.ORMSupportClasses.ORMQueryExecutionException
  HResult=0x80131600
  Message=An exception was caught during the execution of a retrieval query: Failed to convert parameter value from a Byte to a Byte[].. Check InnerException, QueryExecuted and Parameters of this exception to examine the cause of this exception.
  Source=SD.LLBLGen.Pro.ORMSupportClasses
  StackTrace:
   at SD.LLBLGen.Pro.ORMSupportClasses.RetrievalQuery.Execute(CommandBehavior behavior)
   at SD.LLBLGen.Pro.ORMSupportClasses.EntityMaterializerBase.Materialize(Func`4 valueReadErrorHandler, String& failureErrorText)
   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterCore.ExecuteMultiRowRetrievalQuery(IRetrievalQuery queryToExecute, IEntityFactory2 entityFactory, IEntityCollection2 collectionToFill, IFieldPersistenceInfo[] fieldsPersistenceInfo, Boolean allowDuplicates, IEntityFields2 fieldsUsedForQuery)
   at SmartLibrarian.DAL.DatabaseSpecific.DataAccessAdapter.ExecuteMultiRowRetrievalQuery(IRetrievalQuery queryToExecute, IEntityFactory2 entityFactory, IEntityCollection2 collectionToFill, IFieldPersistenceInfo[] fieldsPersistenceInfo, Boolean allowDuplicates, IEntityFields2 fieldsUsedForQuery) in F:\src\SmartLibrarian\SmartLibrarian.DAL\Custom\DataAccessAdapter.cs:line 586

Inner Exception 1:
InvalidCastException: Failed to convert parameter value from a Byte to a Byte[].

Inner Exception 2:
InvalidCastException: Invalid cast from 'System.Byte' to 'System.Byte[]'.

I'll attach a screenshot of the query is trying to generate but the gist of it is that LLBLGen has tried to create a Parameter for each byte!

But the query should look something like this for SQL Server

SELECT * FROM Image WHERE Hash=0xC33608676DA2787A319312A6CE0B81A3D4CFFC82
Attachments
Filename File size Added on Approval
1.png 24,020 25-Apr-2019 15:24.49 Approved
simmotech
User
Posts: 1024
Joined: 01-Feb-2006
# Posted on: 25-Apr-2019 15:30:44   

Panic over!

This predicate works

.Where(ImageFields.Hash.Equal(coverImage.Hash))

But why aren't both filters equivalent?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 25-Apr-2019 15:35:59   

This is a problem with the '==' operator overload. It's defined on EntityField2 and it overloads the '==' operator for various operands: IExpression, object, EntityField2 and... IList. Array implements IList and this matches with this overload, so it will produce a FieldCompareRange predicate as that's what that overload does. In hindsight these overloads for these operators shouldn't have happened, but alas, what's done is done.

To fix this, use .Where(ImageFields.Hash.Equal(coverImage.Hash)). This will produce a FieldCompareValuePredicate as the method to produce an IN() clause is .In(IEnumerable), not .Equal. It's recommended to use the QuerySpec operators btw, and leave the operator overloads for what they are: a relic

(edit) you just beat me to it simple_smile

Frans Bouma | Lead developer LLBLGen Pro