C# 当读卡器关闭时调用Read的尝试无效。(C)

C# 当读卡器关闭时调用Read的尝试无效。(C),c#,sql,sql-server,C#,Sql,Sql Server,我创建了一个从表中获取数据的方法,但它给出了标题中所述的错误。在这里发帖之前,我已经阅读了包括stackoverflow在内的各种网站的许多方法,但这对我没有帮助 下面是我的方法 public SqlDataReader GetCustomer() { SqlDataReader reader = null; _conn = new SqlConnection(connString); string sqlQuery = @"SEL

我创建了一个从表中获取数据的方法,但它给出了标题中所述的错误。在这里发帖之前,我已经阅读了包括stackoverflow在内的各种网站的许多方法,但这对我没有帮助

下面是我的方法

    public SqlDataReader GetCustomer()
    {
        SqlDataReader reader = null;
        _conn = new SqlConnection(connString);
        string sqlQuery = @"SELECT CustName, CustNationality FROM Customer";
        using (_conn)
        {
            using (SqlCommand cmd = new SqlCommand(sqlQuery, _conn))
            {
                _conn.Open();
                reader = cmd.ExecuteReader();
                _conn.Close();
            }
        }
        return reader;
    }
我把这个方法称为

        SqlDataReader reader = null;
        cmboBoxClient.Items.Add("");
        reader = connect.GetCustomer() as SqlDataReader;
        while (reader.Read())
        {
            cmboBoxClient.Items.Add(reader["CustName"] + " " + reader["CustNationality"]);
        }
但是给了我错误,我尝试了IEnumerable方法,但是它给了我转换/强制转换的错误。i、 将IDataReader转换为SqlDataReader。 后来我读到这种方法是不可能的


请建议我。

当您关闭连接时,读卡器将不再有效

在关闭连接和处理命令之前,可以将读取逻辑移动到另一个方法(即GetCustomer)中的循环中

另一种解决方案是使用如下回调:

public void GetCustomer(Action<SqlDataReader> callback)
{
    var connString = "connection_string";

    SqlDataReader reader = null;
    var _conn = new SqlConnection(connString);
    string sqlQuery = @"SELECT CustName, CustNationality FROM Customer";
    using (_conn)
    {
        using (SqlCommand cmd = new SqlCommand(sqlQuery, _conn))
        {
            _conn.Open();
            using(reader = cmd.ExecuteReader())
            {
                callback(reader);
            }
        }
    }
}
connect.GetCustomer((reader =>
{
    while (reader.Read())
    {
        cmboBoxClient.Items.Add(reader["CustName"] + " " + reader["CustNationality"]);
    }
}));
这允许您使GetCustomer方法更通用。您可以多次重复使用它,每次都可以以不同的方式使用读卡器


您可能希望为该方法使用更好的名称。例如,ReadCustomers。

当您关闭连接时,读卡器不再有效

在关闭连接和处理命令之前,可以将读取逻辑移动到另一个方法(即GetCustomer)中的循环中

另一种解决方案是使用如下回调:

public void GetCustomer(Action<SqlDataReader> callback)
{
    var connString = "connection_string";

    SqlDataReader reader = null;
    var _conn = new SqlConnection(connString);
    string sqlQuery = @"SELECT CustName, CustNationality FROM Customer";
    using (_conn)
    {
        using (SqlCommand cmd = new SqlCommand(sqlQuery, _conn))
        {
            _conn.Open();
            using(reader = cmd.ExecuteReader())
            {
                callback(reader);
            }
        }
    }
}
connect.GetCustomer((reader =>
{
    while (reader.Read())
    {
        cmboBoxClient.Items.Add(reader["CustName"] + " " + reader["CustNationality"]);
    }
}));
这允许您使GetCustomer方法更通用。您可以多次重复使用它,每次都可以以不同的方式使用读卡器


您可能希望为该方法使用更好的名称。例如,ReadCustomers。

在返回reader之前,您正在关闭连接。在使用数据库游标时,应保持连接打开。所以,返回读取器并不是最好的选择,因为在调用方使用连接时,您无法处理该连接。我建议您创建强类型类Customer

并在GetCustomers方法中填写客户列表是的,您的查询返回多个客户,而不是单个客户:

public IEnumerable<Customer> GetCustomers()
{
    string sqlQuery = @"SELECT CustName, CustNationality FROM Customer";

    using (var conn = new SqlConnection(connString))        
    using (SqlCommand cmd = new SqlCommand(sqlQuery, conn))
    {
        conn.Open();
        var reader = cmd.ExecuteReader();

        while(reader.Read())
        {
            yield return new Customer {
                Name = (string)reader["CustName"],
                Nationality = (string)reader["CustNationality"]
            };
        }
    }
}
顺便说一句,你可以做所有的查询和映射。所以代码看起来像

public IEnumerable<Customer> GetCustomers()
{
    using (var conn = new SqlConnection(connString))
    {                
        conn.Open();
        return conn.Query<Customer>("SELECT CustName, CustNationality FROM Customer");
    }
}

是的,这就是您所需要的。

在返回读卡器之前,您正在关闭连接。在使用数据库游标时,应保持连接打开。所以,返回读取器并不是最好的选择,因为在调用方使用连接时,您无法处理该连接。我建议您创建强类型类Customer

并在GetCustomers方法中填写客户列表是的,您的查询返回多个客户,而不是单个客户:

public IEnumerable<Customer> GetCustomers()
{
    string sqlQuery = @"SELECT CustName, CustNationality FROM Customer";

    using (var conn = new SqlConnection(connString))        
    using (SqlCommand cmd = new SqlCommand(sqlQuery, conn))
    {
        conn.Open();
        var reader = cmd.ExecuteReader();

        while(reader.Read())
        {
            yield return new Customer {
                Name = (string)reader["CustName"],
                Nationality = (string)reader["CustNationality"]
            };
        }
    }
}
顺便说一句,你可以做所有的查询和映射。所以代码看起来像

public IEnumerable<Customer> GetCustomers()
{
    using (var conn = new SqlConnection(connString))
    {                
        conn.Open();
        return conn.Query<Customer>("SELECT CustName, CustNationality FROM Customer");
    }
}

是的,这就是您所需要的。

从GetCustomer方法返回customer实例,而不是从GetCustomer方法返回readerReturn customer实例,而不是返回Reader,因为在调用方使用连接时无法处理连接,是的,您可以,如果在处理读取器时执行cmd.ExecuteReaderCommandBehavior.CloseConnection,则会关闭基础连接。虽然没有处理连接,但处理连接所做的唯一一件事就是关闭连接,并将几个内部变量调零。这是错误OP的解释——目前,他在调用方使用连接时关闭连接。但无论如何,感谢您指向CommandBehavior选项,抱歉,误解了该语句。因为您无法在调用方使用连接时释放连接,所以可以,如果您执行cmd.ExecuteReaderCommandBehavior.CloseConnection,则在释放读卡器时关闭基础连接。虽然没有处理连接,但处理连接所做的唯一一件事就是关闭连接,并将几个内部变量调零。这是错误OP的解释——目前,他在调用方使用连接时关闭连接。但不管怎样,谢谢你指出命令行为选项啊,对不起,误解了声明。