如何转换DbDataReader至Task <ienumerable <tentity>&gt;在Entity Framework Core 2.0中?

时间:2018-02-01 14:57:01

标签: c# entity-framework asp.net-core entity-framework-core ef-core-2.0

我正在通过以下方式在EF Core 2.0中调用存储过程。

private async Task<IEnumerable<TEntity>> InvokeStoredProcedureAsync(string entityName)
{
    var storedProcedureName = string.Format(CultureInfo.InvariantCulture, "sp_{0}BulkSelect", entityName);
    dynamic temp;
    using (MyDbContext MyDbContext = new MyDbContext(_options))
    {
        MyDbContext.Database.OpenConnection();
        DbCommand cmd = MyDbContext.Database.GetDbConnection().CreateCommand();
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.CommandText = storedProcedureName;

        using (var reader = cmd.ExecuteReader())
        {
           temp = reader.Cast<Task<IEnumerable<TEntity>>>();
        }
    }

    return await temp;
}

我需要从DbDataReader转换为Task<IEnumerable<TEntity>>

但是在尝试扩展temp变量以查看其值时,我收到此错误。

  

关闭阅读器时无法尝试调用FieldCount。

请参阅随附的屏幕截图。

enter image description here

3 个答案:

答案 0 :(得分:5)

除了明显的异步代码问题,您只需调用DbDataReader即可实现Cast课程。如果可能的话,就不需要像Dapper和类似的微型ORM。

EF Core目前没有公开这样做的公开方式。但如果TEntity是模型实体类,则只需使用FromSql方法:

private async Task<IEnumerable<TEntity>> InvokeStoredProcedureAsync(string entityName)
{
    var storedProcedureName = string.Format(CultureInfo.InvariantCulture, "sp_{0}BulkSelect", entityName);
    using (var db = new MyDbContext(_options))
    {
        var result = await db.Set<TEntity>().FromSql(storedProcedureName).ToListAsync();
        return result;
    }
}

确保SP按TEntity映射返回所有预期列。

答案 1 :(得分:0)

当您的读者被调用时,它已经在using - 块完成时关闭。您还需要逐行阅读&#34;&#34;。尝试下面的内容:

private async Task<IEnumerable<TEntity>> InvokeStoredProcedureAsync(string entityName)
{
    var storedProcedureName = string.Format(CultureInfo.InvariantCulture, "sp_{0}BulkSelect", entityName);
    List<TEntity> temp = new List<TEntity>();
    using (MyDbContext MyDbContext = new MyDbContext(_options))
    {
        MyDbContext.Database.OpenConnection();
        DbCommand cmd = MyDbContext.Database.GetDbConnection().CreateCommand();
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.CommandText = storedProcedureName;

        using (var reader = await cmd.ExecuteReaderAsync())
        {
           while (await reader.ReadAsync())
               temp.Add(reader.Cast<TEntity>()); // ATTENTION: this does not work! (see below)
        }
    }

    return temp;
}

但我认为上面使用的演员表并不符合您的想法。有关如何从阅读器创建实体的示例,请参阅以下主题:Convert rows from a data reader into typed results

答案 2 :(得分:0)

在异步方法中,无需转换为任务。这将自己发生。 reader对象有单行。它应该一次读取每一行。

click

async - msdn