2017-01-30 2 views
1

Ich habe ein Problem, wo FirstOrDefaultAsync eine InvalidCastException wirft beim Versuch, eine Zeile aus meiner Datenbank zu bekommen. Wenn ich ohne async auf FirstOrDefault umschalte, lädt es die Daten in Ordnung..NET EntityFramework FirstOrDefaultAync Wurf werfen Fehler

Works

public async Task<Application> GetApplication(int id) 
{ 
    return _context.Applications.FirstOrDefault(a => a.Id == id); 
} 

nicht

public async Task<Application> GetApplication(int id) 
{ 
    return await _context.Applications.FirstOrDefaultAsync(a => a.Id == id); 
} 

Das Schema für die application Tabelle funktionierts sieht so aus:

CREATE TABLE `application` (
    `id` INTEGER NOT NULL, 
    `name` TEXT NOT NULL UNIQUE, 
    `application_id` TEXT NOT NULL UNIQUE, 
    `secret_key` TEXT NOT NULL UNIQUE, 
    PRIMARY KEY(id) 
); 

Die Daten in der Datenbank :

+----+---------+----------------+------------+ 
| id | name | application_id | secret_key | 
+----+---------+----------------+------------+ 
| 1 | TestApp | app123   | secret123 | 
+----+---------+----------------+------------+ 

Die ersten Zeilen des Stack-Trace sind wie folgt:

at System.Data.Common.DbDataReader.GetFieldValue[T](Int32 ordinal) 
at System.Data.Common.DbDataReader.GetFieldValueAsync[T](Int32 ordinal, CancellationToken cancellationToken) 
--- 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) 

Als id das einzige Int32 Feld in der Tabelle ist, ich bin EF erraten ist mit dieser Eigenschaft zu kämpfen, aber ich kann nicht herausfinden, warum es funktioniert, wenn FirstOrDefault verwendet wird. Irgendwelche Ideen?

Ich benutze Entity Framework 6 mit .NET 4.5.1.

Vielen Dank im Voraus!

+0

verwenden 'FindAsync (id)'. Diese Erweiterungsmethode ist im Grunde entworfen, um mit Primärschlüssel zu arbeiten. –

Antwort

1

Können Sie Ihre Frage aktualisieren, da das, was Sie sagen, funktioniert, sollte wirklich nicht - FirstOrDefault() gibt keine Aufgabe zurück, so würden Sie eine Besetzung Ausnahme dort erhalten.

Was Sie brauchen, ist

public async Task<Application> GetApplicationAsync(int id) 
{ 
    return await _context.Applications.FirstOrDefaultAsync(a => a.Id == id); 
} 
+0

Das ist, was ich in meiner Frage unter "funktioniert nicht" habe :) Ich bin mir bewusst, dass Sie normalerweise nicht Aufgabe für eine nicht-asynchrone zurückgeben Methode, aber es gibt immer noch die Entität gut. – Tom

+0

Ich sollte auch beachten, dass ich nicht beide Implementierungen zur gleichen Zeit deklariert habe, ich ändere nur den Körper. Es gibt keine zwei "Task GetApplication (int id)" Methoden. – Tom

1

Da Sie Asynchron-Methode verwenden, so dass Sie

public async Task<Application> GetApplication(int id) 
{ 
    return await _context.Applications.FirstOrDefaultAsync(a => a.Id == id); 
} 

Aber eigentlich Ihre Id Spalte Primärschlüssel verwenden müssen, so dass Sie einen anderen Linq Extension-Methode verwenden können, für Ihre Aufgabe wie

public async Task<Application> GetApplication(int id) 
{ 
    return await _context.Applications.FindAsync(id); 
} 

FindAsync(id) ist grundsätzlich für 012 ausgelegtbasierte Auswahl. Daher wird empfohlen, FindAsync() zu verwenden. In

Namespace: System.ServiceModel.Discovery Assembly: System.ServiceModel.Discovery (in System.ServiceModel.Discovery.dll)

Eigentlich Sie verwenden, und ich denke, SQLite ist nicht einfädeln -safe, also sollten Sie nicht einmal wollen, dass Async-Anfragen bearbeitet werden. Es gibt eine Bibliothek, die Sqlite asynchron macht, aber ich weiß nicht, ob es gut funktioniert. aber versuchen Sie github.com/oysteinkrog/SQLite.Net-PCL

+0

Welcher Namespace ist 'FindAsync' unter? Ich habe 'Find', aber nicht' FindAsync'. Mit Blick auf die MSDN-Dokumente sollte es für EF6 da sein, also ist das ein wenig verwirrend! – Tom

+0

Wenn es nicht funktioniert, müssen Sie mit .NET 4.5.1 statt 4.5 kompilieren und Sie erhalten im Allgemeinen bessere Exception-Traces mit async. –

+0

Eigentlich habe ich festgestellt, dass es fehlt, weil ich 'IDbSet ' und nicht 'verwende DbSet '- wechselte zu' DbSet 'und jetzt habe ich die' FindAsync' Methode. Die Verwendung von 'FindAsync' hat das Problem jedoch nicht gelöst - immer noch die' InvalidCastException' :( – Tom