paulyoder / LinqToExcel

Use LINQ to retrieve data from spreadsheets and csv files

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Nullable Types throwing exception

BenVlodgi opened this issue · comments

It's telling me 'HasValue' is not a valid column name. when I'm targeting the HasValue property of my IncludeInFlex header property of my class (which is nullable).

public class Token
{
    public bool? IncludeInFlex { get; set; }
    public string Name { get; set; }
    public string English { get; set; }
}
var excel = new ExcelQueryFactory(arg) { ReadOnly = true };
excel.AddMapping<Token>(x => x.IncludeInFlex, "Include In Flex", str => str.ToLower() == "yes" ? true : str.ToLower() == "no" ? false : (bool?)null);

excel.Where(token => token.IncludeInFlex.HasValue && token.IncludeInFlex.Value);

Throws exception
Message: 'HasValue' is not a valid column name. Valid column names are: 'Include In Flex', 'TokenEntry', 'en', 'de', 'F5', 'F6', 'F7', 'F8'

TargetSite: {Boolean CheckIfInvalidColumnNameUsed(LinqToExcel.Query.SqlParts)}

StrackTrace:

   at LinqToExcel.Query.ExcelQueryExecutor.CheckIfInvalidColumnNameUsed(SqlParts sql)
   at LinqToExcel.Query.ExcelQueryExecutor.GetDataResults(SqlParts sql, QueryModel queryModel)
   at LinqToExcel.Query.ExcelQueryExecutor.ExecuteCollection[T](QueryModel queryModel)
   at Remotion.Data.Linq.Clauses.StreamedData.StreamedSequenceInfo.ExecuteCollectionQueryModel[T](QueryModel queryModel, IQueryExecutor executor)
   at Remotion.Data.Linq.Clauses.StreamedData.StreamedSequenceInfo.ExecuteQueryModel(QueryModel queryModel, IQueryExecutor executor)
   at Remotion.Data.Linq.QueryModel.Execute(IQueryExecutor executor)
   at Remotion.Data.Linq.QueryProviderBase.Execute[TResult](Expression expression)
   at Remotion.Data.Linq.QueryableBase`1.GetEnumerator()
   at System.Linq.Enumerable.<SelectManyIterator>d__16`2.MoveNext()
   at System.Linq.Lookup`2.Create[TSource](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
   at System.Linq.GroupedEnumerable`3.GetEnumerator()
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
   at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
   at System.Linq.OrderedEnumerable`1.<GetEnumerator>d__1.MoveNext()
   at System.Linq.Lookup`2.Create[TSource](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
   at System.Linq.GroupedEnumerable`3.GetEnumerator()
   at System.Linq.Enumerable.<SelectManyIterator>d__16`2.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at DematicLanguageFileManager.Program.ProcessExcelLinqFiles(String[] args, String saveDir) in c:\users\blodgebt\documents\visual studio 2015\Projects\DematicLanguageFileManager\DematicLanguageFileManager\Program.cs:line 64
   at DematicLanguageFileManager.Program.Main(String[] args) in c:\users\blodgebt\documents\visual studio 2015\Projects\DematicLanguageFileManager\DematicLanguageFileManager\Program.cs:line 47
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly 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.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

@BenVlodgi. Did you come with a solution on how to read Nullable fields from Excel?

No, instead I just read the text value in and used that.

public class Token
{
    public string IncludeInFlex { get; set; }
    public string Name { get; set; }
    public string English { get; set; }
}

If I wanted to, I could then transform this object into a dataobject of my choosing (which then may use the nullable types).

public class TokenData
{
    public bool? IncludeInFlex { get; set; }
    public string Name { get; set; }
    public string English { get; set; }

    public TokenData GetFromToken(Token token)
    {
        return new TokenData()
        {
            IncludeInFlex = token.IncludeInFlex != null ?
                                token.IncludeInFlex.ToLower() == "yes" ? true :
                                token.IncludeInFlex.ToLower() == "no" ? false :
                                default(bool?) : 
                            default(bool?),
            Name = token.Name,
            English = token.English
        };
    }
}

I did make a change the other day that fixed an issue with using nullable types in aggregate functions, not sure if the code changed there would help this issue specifically. I will investigate. I know this issue's old, but it would be nice if this sort of thing worked, or if at least a decent work-around was made possible.