2014-09-30 5 views
7

Я использую следующую строку кода для запроса некоторых данных из данной таблицы в базе данных SQLite (платформа WP81, но я думаю, это не имеет значения здесь).SQLite.net table query throws NullReferenceException

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

Когда я выполняю свой код, я получаю исключение NullReferenceException в предложении Where. Когда я удаляю условие, все работает нормально.

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

Для того, чтобы убедиться, что все записи в моей таблице, действительны и не нулевое значение в столбце Date я использовал инструмент SQL, чтобы посмотреть в базу данных SQLite.

Поскольку я не могу отлаживать лямбда-выражения, я как бы застрял в том, как найти проблему здесь. Мое предположение заключается в том, что что-то пойдет не так из-за асинхронной обработки.

Edit: Вот точный StackTrace за исключением

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

Я играл немного больше и выяснили следующее.

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

При выполнении этого заявления он фактически распадается в методе ToListAsync() вместо метода Where. Однако это тоже не помогает.

Позже я попробовал следующее, которое фактически работает.

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

Так что я сделал, чтобы отделить метод Where на самом деле. Но хотя это работает для меня, это не отвечает на мой вопрос, потому что я все еще удивляюсь, почему это не работает.

+0

Что вы подразумеваете под «NRE in where where clause»? Если он фактически компилируется в дерево выражений и обрабатывается как таковой, не должно быть возможным, чтобы сама лямбда выдавала исключение, а только код, который ее обрабатывает. Вы действительно получаете исключение, прежде чем «ToListAsync» когда-либо называется, или вы просто имеете в виду «если я удалю« Where », нет исключения»? –

+0

Определены переменные 'from' и' to'? Я также вижу, что 'to' здесь не имеет' @ '. и у вас есть null 'Date' в 'WorkDay'? – MPelletier

+0

@MPelletier Да. Я проверил, используя отладчик, что и от, и до значения. from имеет @, потому что это также ключевое слово в C#, и поэтому обычно не разрешается использовать переменную с этим именем. – Stephan

ответ

1

Возможно, я слишком новичок, чтобы узнать, о чем говорю, но, думаю, вашему последнему примеру просто нужно было сделать заявление await перед вызовом ToListAsync.

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

Не уверен, что о специфике первой проблемы, но я думаю, что это что-то делать с объектом TableAsyncQuery, что где оператор производит, не полностью инициализирован перед ToListAsync называет его в другом потоке ,

+0

К сожалению, я не могу это проверить, поскольку вместо SQLite (iBoxDB) я использую другую базу данных. Но я уверен, что Visual Studio будет жаловаться на случай, если я попытаюсь получить доступ к результату Task без асинхронизации там. Но я могу ошибаться. – Stephan

Смежные вопросы