【问题标题】:System.InvalidOperationException: Invalid attempt to call FieldCount when reader is closedSystem.InvalidOperationException:读取器关闭时调用 FieldCount 的尝试无效
【发布时间】:2021-08-29 07:33:28
【问题描述】:
  1. 我希望 queryOutput 能够实现?
  2. 为什么 当 fieldcount 已经有 IEnumerable 时,是否尝试调用 fieldcount 无效?

/// <summary>
   /// Get all columns for a certain table
   /// </summary>
   public async Task<List<Tuple<string, string, int?>>> GetAllColumnsFromTableAsync(string tableName)
{
    List<Tuple<string, string, int?>> result;
    string query = "SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME= @tableName";
    using (IDbConnection db = DbConnection) 
    { 
        IEnumerable<Tuple<string, string, int?>> queryOutput = await db.QueryAsync<string, string, int?, Tuple<string, string, int?>>
            (query, Tuple.Create, new { tableName = tableName }, null, false, splitOn: "*");
        result = queryOutput.ToList(); // System.InvalidOperationException: Invalid attempt to call FieldCount when reader is closed.
    }

    if (result is not null && result.Count > 0)
    {
        return result;
    }
    else
    {
        return default;
    }
}

  • 将此作为非异步方法有效。所以它必须是“tuple”+“dapper”+“async”

参考:https://github.com/DapperLib/Dapper/issues/745

更新:

  1. 当用命名元组替换元组时,查询本身 有效。

    public async Task<List<(string COLUMN_NAME, string DATA_TYPE, int? CHARACTER_MAXIMUM_LENGTH)>> GetAllColumnsFromTableAsync2(string tableName)
    {
        const string query = "SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME= @tableName";
        using var connection = new SqlConnection(_connectionstring);
        var output = await connection.QueryAsync<(string COLUMN_NAME, string DATA_TYPE, int? CHARACTER_MAXIMUM_LENGTH)>
                (query, new { tableName = tableName });
        return output.ToList();
    }
    

我还有一个问题,但这是另一个问题。

【问题讨论】:

  • Dapper 文档指出查询结果是 List 实例,因此我通常执行以下操作:return connection.Query&lt;MyDto>(sql) as IList;`
  • 退出 using 块前需要等待结果。
  • @john-wu 据我所知,我正在等待“等待”的结果? (并将 {} 放在我添加的 using 周围,以查看这是否会产生影响,因为它们不需要
  • @RoarS。据我所知,我做'tolist'?
  • 我的猜测是DbConnection 关闭得太早了。我无法从您的代码中看到它是在哪里创建的。如果您尝试用我的答案中的相同代码替换代码的那部分,那可以验证/伪造。

标签: c# sql-server .net-core dapper


【解决方案1】:

Dapper 应该让你的生活更轻松,而代码看起来很复杂。

如果您使用带有命名字段的Tuple,您可以只使用 Dapper 的自动映射来实现。例如:

static class DbExtensions
{
    public static async Task<List<(string COLUMN_NAME, string DATA_TYPE, int? CHARACTER_MAXIMUM_LENGTH)>> GetAllColumnsFromTableAsync(this IDbConnection db, string tableName, string schema = "dbo")
    {
        string query = "SELECT COLUMN_NAME, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME= @tableName and TABLE_SCHEMA=@schema";
        var queryOutput = await db.QueryAsync<(string COLUMN_NAME, string DATA_TYPE, int? CHARACTER_MAXIMUM_LENGTH)>(query, new { tableName = tableName, schema = schema });
        return queryOutput.ToList();
    }
}

另请注意,如果您有多个同名表,则查询中存在错误,因此您应该指定架构。

【讨论】:

  • 巧妙的技巧,总是使用 .item。将在代码库中向后重构。这可行,但是......我需要在使用 Roar S 之前使用“等待”。他的回答也是,否则我的其他并行运行状况检查会显示间歇性 sql 错误。
  • “使用前先使用”await”是什么意思?
  • Roar S. 的回答表明他使用“await using var connection”,所以该行中的“await”一词。
  • 它对await 构造函数没有任何事情。它们总是同步的。
  • 我将进一步检查为什么 using DOES 确实解决了问题,尽管它没有做任何事情。由于没有间歇性错误,因此它会有所作为,但可能不是主要原因,而是副作用。
猜你喜欢
  • 2011-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-29
  • 1970-01-01
  • 1970-01-01
  • 2011-08-26
  • 1970-01-01
相关资源
最近更新 更多