2014-09-30 12 views
7

Tôi đang sử dụng các dòng mã sau đây để truy vấn một số dữ liệu từ một bảng được đưa ra trong một cơ sở dữ liệu SQLite (nền tảng là WP81 nhưng tôi đoán này không quan trọng ở đây).truy vấn bảng SQLite.net ném NullReferenceException

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

Khi tôi thực thi mã, tôi nhận được NullReferenceException trong mệnh đề Where. Khi tôi loại bỏ điều kiện nơi mọi thứ hoạt động tốt.

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

Để đảm bảo tất cả các mục nhập trong bảng của tôi hợp lệ và không có giá trị null trong cột Ngày, tôi đã sử dụng công cụ SQL để xem cơ sở dữ liệu SQLite.

Như tôi có thể không biểu thức lambda debug tôi là loại mắc kẹt trên làm thế nào để tìm thấy vấn đề ở đây. Giả định của tôi là có điều gì đó sai do xử lý không đồng bộ.

Edit: Đây là stacktrace chính xác của các ngoại lệ

{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)} 

Chỉnh sửa 2:

tôi đã chơi xung quanh một chút hơn và tìm ra những điều sau đây.

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

Khi thực hiện câu lệnh này, nó thực sự phá vỡ phương thức ToListAsync() thay cho phương thức Where. Tuy nhiên, điều này cũng không giúp được gì.

Sau đó tôi cố gắng sau đó thực sự hoạt động.

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

Vì vậy, những gì tôi đã làm là tách riêng phương thức Where. Nhưng mặc dù điều này làm việc cho tôi nó không trả lời câu hỏi của tôi bởi vì tôi vẫn tự hỏi tại sao điều này không hoạt động.

+0

Ý anh là gì bởi "TNMT trong mệnh đề where"? Nếu nó thực sự biên soạn thành một cây biểu hiện và được xử lý như vậy, nó không phải là có thể cho lambda bản thân để ném một ngoại lệ, chỉ có mã mà xử lý nó. Bạn có thực sự có được một ngoại lệ trước khi "ToListAsync" là bao giờ gọi, hoặc cậu chỉ có nghĩa là "nếu tôi loại bỏ các trường hợp, không có ngoại lệ" bằng cách đó? –

+0

Biến 'from' và' to' của bạn có được xác định không? Tôi cũng thấy 'to' ở đây không có' @ '. và bạn có null 'Date' trong 'WorkDay'? – MPelletier

+0

@MPelletier Có. Tôi đã kiểm tra bằng cách sử dụng trình gỡ lỗi mà cả hai, từ và để có một giá trị. từ có @ bởi vì nó cũng là một từ khóa trong C# và do đó nó thường không được phép sử dụng một biến với tên đó. – Stephan

Trả lời

1

Có lẽ tôi quá mới để biết tôi đang nói về điều gì, nhưng tôi nghĩ ví dụ cuối cùng của bạn chỉ cần một tuyên bố await trước cuộc gọi ToListAsync của bạn.

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

Không chắc chắn về những đặc trưng của vấn đề đầu tiên, nhưng tôi sẽ nghĩ rằng nó có cái gì để làm với các đối tượng TableAsyncQuery, rằng tuyên bố ở đâu sản xuất, không được khởi tạo đầy đủ trước khi ToListAsync gọi nó trên thread khác .

+0

Thật không may, tôi không thể kiểm tra điều này nữa vì tôi đang sử dụng cơ sở dữ liệu khác thay vì SQLite (iBoxDB). Nhưng tôi khá chắc chắn rằng Visual Studio sẽ khiếu nại trong trường hợp tôi sẽ cố gắng truy cập vào một kết quả Task với ra async ở đó. Nhưng tôi có thể nhầm. – Stephan

Các vấn đề liên quan