Filtering projected enum fields 2.6 vs 3.1

Posts   
 
    
AlbertK
User
Posts: 44
Joined: 23-Dec-2009
# Posted on: 05-Oct-2011 00:00:24   

Hello, I'm running into a problem with the following type of code in 3.1.11 (latest) and .NET 4.0, but it works with 2.6.10 and .NET 3.5. Is this no longer a supported scenario?

Here's code snippet:


public class MyProjection
{
    public int ListId;
    public EnumListType ListType; //enum is int based
}

var q = from c in metaData.SomeEntity
        select new MyProjection
        {
            ListId = c.ListId,
            ListType = (EnumListType)c.ListTypeId
        };

if (listFilter.HasValue) //ListFilter is defined as EnumListType?
    q = q.Where(x => x.ListType == listFilter.Value);

var list = q.ToList();

The entity field I want to (optionally) filter by is an int. However, the filter is passed as an enum. My workaround, was to define an extra field of type int in MyProjection class, project value into that field and filter by that value. Then, after I obtained list in memory, I set the enum field. It would be nice to not have to do this, especially because this worked in 2.6.10.

Here's the stack trace for the error in 3.1.11 as soon as query expression is evaluated.

System.ArgumentNullException: Value cannot be null. Parameter name: conversionType at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider) at System.Convert.ChangeType(Object value, Type conversionType) at SD.LLBLGen.Pro.ORMSupportClasses.DbSpecificCreatorBase.GetRealValue(Object currentValue, TypeConverter typeConverterToUse, Type actualDotNetType, Boolean valueIsEnumTyped) at SD.LLBLGen.Pro.ORMSupportClasses.DbSpecificCreatorBase.CreateParameter(IEntityFieldCore field, IFieldPersistenceInfo persistenceInfo, ParameterDirection direction, Object valueToSet) at SD.LLBLGen.Pro.ORMSupportClasses.FieldCompareValuePredicate.ToQueryText(Boolean inHavingClause) at SD.LLBLGen.Pro.ORMSupportClasses.PredicateExpression.ToQueryText(Boolean inHavingClause) at SD.LLBLGen.Pro.ORMSupportClasses.PredicateExpression.ToQueryText(Boolean inHavingClause) at SD.LLBLGen.Pro.ORMSupportClasses.PredicateExpression.ToQueryText(Boolean inHavingClause) at SD.LLBLGen.Pro.ORMSupportClasses.PredicateExpression.ToQueryText(Boolean inHavingClause) at SD.LLBLGen.Pro.ORMSupportClasses.PredicateExpression.ToQueryText() at SD.LLBLGen.Pro.ORMSupportClasses.DynamicQueryEngineBase.AppendWhereClause(IPredicate filter, QueryFragments destination, IQuery query) at SD.LLBLGen.Pro.DQE.SqlServer.DynamicQueryEngine.CreateSelectDQ(IEntityFieldCore[] selectList, IFieldPersistenceInfo[] fieldsPersistenceInfo, IRetrievalQuery query, IPredicate selectFilter, Int64 maxNumberOfItemsToReturn, ISortExpression sortClauses, IRelationCollection relationsToWalk, Boolean allowDuplicates, IGroupByCollection groupByClause, Boolean relationsSpecified, Boolean sortClausesSpecified) at SD.LLBLGen.Pro.ORMSupportClasses.DynamicQueryEngineBase.CreateSelectDQ(IEntityFieldCore[] selectList, IFieldPersistenceInfo[] fieldsPersistenceInfo, DbConnection connectionToUse, IPredicate selectFilter, Int64 maxNumberOfItemsToReturn, ISortExpression sortClauses, IRelationCollection relationsToWalk, Boolean allowDuplicates, IGroupByCollection groupByClause) at SD.LLBLGen.Pro.DQE.SqlServer.DynamicQueryEngine.CreatePagingSelectDQ(IEntityFieldCore[] selectList, IFieldPersistenceInfo[] fieldsPersistenceInfo, DbConnection connectionToUse, IPredicate selectFilter, Int64 maxNumberOfItemsToReturn, ISortExpression sortClauses, IRelationCollection relationsToWalk, Boolean allowDuplicates, IGroupByCollection groupByClause, Int32 pageNumber, Int32 pageSize) at SD.LLBLGen.Pro.ORMSupportClasses.DynamicQueryEngineBase.CreateSelectDQ(IEntityFieldCore[] selectList, IFieldPersistenceInfo[] fieldsPersistenceInfo, DbConnection connectionToUse, IPredicate selectFilter, Int64 maxNumberOfItemsToReturn, ISortExpression sortClauses, IRelationCollection relationsToWalk, Boolean allowDuplicates, IGroupByCollection groupByClause, Int32 pageNumber, Int32 pageSize) at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.CreateSelectDQ(IEntityFields2 fieldsToFetch, IFieldPersistenceInfo[] persistenceInfoObjects, IPredicateExpression filter, Int64 maxNumberOfItemsToReturn, ISortExpression sortClauses, IRelationCollection relationsToWalk, Boolean allowDuplicates, IGroupByCollection groupByClause, Int32 pageNumber, Int32 pageSize) at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.CreateQueryFromElements(IEntityFields2 fieldCollectionToFetch, IRelationPredicateBucket filterBucket, Int32 maxNumberOfItemsToReturn, ISortExpression sortClauses, Boolean allowDuplicates, IGroupByCollection groupByClause, Int32 pageNumber, Int32 pageSize, IFieldPersistenceInfo[]& persistenceInfo, IRetrievalQuery& selectQuery) at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.FetchProjection(List`1 valueProjectors, IGeneralDataProjector projector, IEntityFields2 fields, IRelationPredicateBucket filter, Int32 maxNumberOfItemsToReturn, ISortExpression sortClauses, IGroupByCollection groupByClause, Boolean allowDuplicates, Int32 pageNumber, Int32 pageSize) at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProvider2.ExecuteValueListProjection(QueryExpression toExecute) at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.ExecuteExpression(Expression handledExpression) at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.Execute(Expression expression) at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.System.Linq.IQueryProvider.Execute[TResult](Expression expression)

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 05-Oct-2011 05:22:32   

I think the reason is that you are filtering on top of the first query which has the projection, thus the projection is not the last one. When you use a select projection it has to be the last projection. Do you still receive the error if you do something like this?:

var q = from c in metaData.SomeEntity
        where c. ListTypeId == listFilter.Value
        select new MyProjection
        {
            ListId = c.ListId,
            ListType = c.ListTypeId
        };

var list = q.ToList();

Also, now in v3.x you can import enum types and use them in your entity fiels. Read more about this.

David Elizondo | LLBLGen Support Team
AlbertK
User
Posts: 44
Joined: 23-Dec-2009
# Posted on: 05-Oct-2011 17:24:32   

If I do the filtering in the where clause as you suggested, it works ok. But, the reason I construct the where clause outside of the first query is because I want the where clause to be optional. I've intentionally reduced the example to a minimum, but I append various where clauses based on multiple filters passed in from UI. This mechanism has no issues with dates or booleans. It just seems to be an issue with enums.

I'll review your suggestion about enum types. Thanks.

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 06-Oct-2011 03:06:32   

AlbertK wrote:

If I do the filtering in the where clause as you suggested, it works ok. But, the reason I construct the where clause outside of the first query is because I want the where clause to be optional. I've intentionally reduced the example to a minimum, but I append various where clauses based on multiple filters passed in from UI. This mechanism has no issues with dates or booleans. It just seems to be an issue with enums.

If you are adding where clauses dinamically maybe you would be interested in PredicateBuilder: http://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=14144&StartAtMessage=0&#78965

David Elizondo | LLBLGen Support Team