System.InvalidOperationException:关闭 reader 时尝试调用 FieldCount 无效

System.InvalidOperationException: Invalid attempt to call FieldCount when reader is closed

  1. 我会期望 queryOutput 被实现吗?
  2. 为什么 当它已经有 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;
    }
}

参考: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 应该让您的生活更轻松,但代码看起来很复杂。

如果您使用带有命名字段的 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();
    }
}

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