簡體   English   中英

如何在Entity Framework Core 2.0中從DbDataReader轉換為Task <IEnumerable <TEntity >>?

[英]How to convert from DbDataReader to Task<IEnumerable<TEntity>> in Entity Framework 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。

請參閱隨附的屏幕截圖。

在此輸入圖像描述

除了明顯的異步代碼問題之外,您無法通過簡單地調用Cast來將DbDataReader為類。 如果可能的話,就不需要像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映射返回所有預期的列。

在您的閱讀器被調用時,它已經關閉,因為using -block已經完成。 你還需要閱讀“逐行”。 嘗試下面的內容:

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

但我認為上面使用的演員表並不符合您的想法。 有關如何從讀取器創建實體的示例,請參閱以下線程: 將數據讀取器中的行轉換為鍵入的結果

在異步方法中,無需強制轉換為任務。 這將自己發生。 reader對象有單行。 應該一次讀取每一行。

var temp = new List<TEntity>();

  using (var reader = await  cmd.ExecuteReaderAsync()) {
    while(await reader.ReadAsync()) {
        temp.add(CreateEntity(reader)) ;
     }
   }

return temp;

// this is tightly coupled to object. Generic methods can be made
//  to convert reader to object
public TEntity CreateEntity(SqlDataReader reader) => new TEntity()
    {
        Id = reader.GetInt32("id"),
        Col1 =  reader.GetString("col1"),
        Col2 =  reader.GetString("col2"),
        Col3 =  reader.GetString("col3")
    };

async - msdn

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM