2014-09-30 16 views
7

Korzystam z poniższego wiersza kodu, aby wysłać zapytanie do niektórych danych z danej tabeli w bazie danych SQLite (platforma to WP81, ale myślę, że to nie ma znaczenia).Zapytanie tabeli SQLite.net zgłasza NullReferenceException

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

Kiedy wykonać mój kod otrzymuję NullReferenceException w klauzuli WHERE. Kiedy usuwam warunek, gdzie wszystko działa poprawnie.

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

W celu upewnienia się, że wszystkie wpisy w moim stole są ważne i nie ma wartość null w kolumnie Data użyłem narzędzia SQL zajrzeć do bazy danych SQLite.

Ponieważ nie mogę debugować wyrażeń lambda, utknąłem na tym, jak znaleźć problem tutaj. Zakładam, że coś poszło nie tak z powodu obsługi asynchronicznej.

Edit: Oto dokładny StackTrace wyjątku

{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:

Grałem około trochę więcej i zorientowali się, co następuje.

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

Podczas wykonywania tej instrukcji faktycznie włamuje się do metody ToListAsync() zamiast metody Where. Jednak to też nie pomaga.

Później próbowałem następujących, które faktycznie działa.

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

Więc to, co zrobiłem, to oddzielenie metody Where w rzeczywistości. Ale chociaż to działa dla mnie, to nie odpowiada na moje pytanie, ponieważ wciąż zastanawiam się, dlaczego to nie działa.

+0

Co masz na myśli przez "NRE w klauzuli where"? Jeśli faktycznie kompiluje się w drzewo wyrażeń i jest przetwarzane jako takie, nie powinno być możliwe, aby sama lambda wyrzuciła wyjątek, a jedynie kod, który je przetwarza. Czy rzeczywiście otrzymujesz wyjątek przed wywołaniem "ToListAsync", czy też masz na myśli "jeśli usunę Gdzie, nie ma wyjątku"? –

+0

Czy zdefiniowano zmienne "od" i "do"? Widzę też, że 'to' tutaj nie ma' @ '. i czy masz null 'Date's w' WorkDay'? – MPelletier

+0

@ MPelletier Tak. Sprawdziłem przy użyciu debuggera, który zarówno od i do mieć wartość. from ma znak @, ponieważ jest również słowem kluczowym w języku C# i dlatego zazwyczaj nie można używać zmiennej o tej nazwie. – Stephan

Odpowiedz

1

Może jestem zbyt nowe, aby wiedzieć, co mówię, ale myślę, że tylko ostatni przykład potrzebne oświadczenie await przed rozmowy ToListAsync.

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

Nie wiesz od specyfiki pierwszego problemu, ale myślę, że to ma coś wspólnego z obiektem TableAsyncQuery, że Jeżeli oświadczenie produkuje, nie będąc w pełni zainicjowany przed nazywa go ToListAsync w innym wątku .

+0

Niestety, nie mogę tego przetestować, ponieważ używam teraz innej bazy danych zamiast SQLite (iBoxDB). Ale jestem całkiem pewny, że Visual Studio będzie narzekać na wypadek, gdybym spróbował uzyskać dostęp do wyniku zadania bez asynchronizacji w tym miejscu. Ale mogę się mylić. – Stephan

Powiązane problemy