2014-09-30 8 views
7

Sto usando la seguente riga di codice per interrogare alcuni dati da una data tabella in un database SQLite (la piattaforma è WP81 ma immagino che questo non contenga qui).La query della tabella SQLite.net genera NullReferenceException

return await Connection.Table<WorkDay>().Where(wd => wd.Date >= @from && wd.Date <= to).ToListAsync().ConfigureAwait(false); 

Quando eseguo il mio codice ottengo un NullReferenceException nella clausola Where. Quando rimuovo la condizione dove tutto funziona correttamente.

return await Connection.Table<WorkDay>().ToListAsync().ConfigureAwait(false); 

Al fine di assicurarsi che tutte le voci nella mia tabella sono validi e non v'è alcun valore nullo nella colonna Data che ho usato uno strumento SQL per esaminare il database SQLite.

Poiché non riesco a eseguire il debug delle espressioni lambda, sono piuttosto bloccato su come trovare il problema qui. La mia ipotesi è che qualcosa vada storto a causa della gestione asincrona.

Edit: Ecco la StackTrace esatto di eccezione

{System.NullReferenceException: Object reference not set to an instance of an object. 
    at SQLite.Net.TableQuery`1.CompileExpr(Expression expr, List`1 queryArgs) 
    at SQLite.Net.TableQuery`1.CompileExpr(Expression expr, List`1 queryArgs) 
    at SQLite.Net.TableQuery`1.CompileExpr(Expression expr, List`1 queryArgs) 
    at SQLite.Net.TableQuery`1.GenerateCommand(String selectionList) 
    at SQLite.Net.TableQuery`1.GetEnumerator() 
    at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) 
    at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source) 
    at SQLite.Net.Async.AsyncTableQuery`1.<ToListAsync>b__0() 
    at System.Threading.Tasks.Task`1.InnerInvoke() 
    at System.Threading.Tasks.Task.Execute() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult() 
    at TimeStamp.Core.Services.DataService.<GetWorkDays>d__c.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() 
    at TimeStamp.Core.ViewModel.MainViewModel.<LoadWorkDays>d__1a.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__3(Object state)} 

Edit 2:

Ho suonato in giro un po 'di più e capito quanto segue.

var query = Connection.Table<WorkDay>().Where(wd => wd.Date >= @from && wd.Date <= to); 
return query.ToListAsync().ConfigureAwait(false); 

Quando si esegue questa dichiarazione in realtà rompe nel metodo anziché il metodo Dove ToListAsync(). Tuttavia, questo non aiuta neanche.

Successivamente ho provato quanto segue che funziona effettivamente.

var result = await Connection.Table<WorkDay>().ToListAsync().ConfigureAwait(false); 
return result.Where(wd => wd.Date >= @from && wd.Date <= to).ToList(); 

Quindi quello che ho fatto è separare il metodo Where in realtà. Ma anche se questo funziona per me, non risponde alla mia domanda perché mi sto ancora chiedendo perché questo non funziona.

+0

Cosa intendi con "NRE nella clausola where"? Se in realtà si sta compilando in un albero di espressioni e viene elaborato come tale, non dovrebbe essere possibile per il lambda stesso lanciare un'eccezione, solo il codice che lo elabora. In effetti ricevi un'eccezione prima che venga chiamato "ToListAsync", o intendevi semplicemente "se rimuovo Where, non ci sono eccezioni"? –

+0

Le variabili 'from' e' to' sono definite? Vedo anche che 'to' qui non ha un' @ '. e hai 'Date's nullo in' WorkDay'? – MPelletier

+0

@MPelletier Sì. Ho controllato usando il debugger che entrambi, da e per avere un valore. da ha @ perché è anche una parola chiave in C# e quindi di solito non è permesso usare una variabile con quel nome. – Stephan

risposta

1

Forse sono troppo nuovo per sapere di cosa sto parlando, ma credo che il tuo ultimo esempio avesse appena bisogno di una dichiarazione await prima della tua chiamata ToListAsync.

var query = Connection.Table<WorkDay>().Where(wd => wd.Date >= @from && wd.Date <= to); 
return await query.ToListAsync().ConfigureAwait(false); 

Non sono sicuro sulle specifiche del primo problema, ma vorrei pensare che ha qualcosa a che fare con l'oggetto TableAsyncQuery, che la dichiarazione Dove produce, non essere inizializzato completamente prima della ToListAsync chiama su un altro thread .

+0

Sfortunatamente, non riesco a testarlo più mentre sto usando un altro database ora invece di SQLite (iBoxDB). Ma sono abbastanza sicuro che Visual Studio si lamenterebbe nel caso in cui provassi ad accedere a un risultato di Task senza async. Ma potrei sbagliarmi. – Stephan