.NET EntityFramework FirstOrDefaultAync抛出强制转换错误

时间:2017-01-30 09:24:45

标签: .net entity-framework sqlite asynchronous

在尝试从我的数据库中获取行时,我遇到了使用FirstOrDefaultAsync抛出InvalidCastException的问题。如果我在没有异步的情况下切换到FirstOrDefault,那么它会正确加载数据。

作品

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

不起作用

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

application表的架构如下所示:

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)
);

数据库中的数据是:

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

堆栈跟踪的前几行如下:

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)

由于id是表格中唯一的Int32字段,我猜测EF正在努力使用此属性,但我无法解决使用FirstOrDefault时其工作原理的问题。有什么想法吗?

我正在使用.NET 4.5.1的实体框架6。

提前致谢!

2 个答案:

答案 0 :(得分:1)

你能否更新你的问题,正如你所说的那样,真的不应该 - FirstOrDefault()不会返回Task,所以你会得到一个强制转换异常。

您需要的是

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

答案 1 :(得分:1)

由于您使用的是异步方法,因此需要使用

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

但实际上您的Id列是主键,因此您可以使用其他linq扩展方法来完成您的任务,例如

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

FindAsync(id)基本上是为基于primary key的选择而设计的。所以建议使用FindAsync()。添加

  

命名空间:System.ServiceModel.Discovery       程序集:System.ServiceModel.Discovery(在System.ServiceModel.Discovery.dll中)

实际上你正在使用,我认为Sqlite不是线程安全的,所以你甚至不希望它处理异步请求。有一个库可以使Sqlite异步,但我不知道它是否运行良好。但请尝试github.com/oysteinkrog/SQLite.Net-PCL