0
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.SqlClient; // need this for database connection

namespace DatabaseTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void connectButton_Click(object sender, EventArgs e)
        {
         
            string connectionString;
            SqlConnection cnn;

            connectionString = "Server= xxx; Database= nba_database; Integrated Security=True"; // xxx is a placeholder, my connection string is right. Censoring it for privacy 


            cnn = new SqlConnection(connectionString);

            cnn.Open();
            MessageBox.Show("Connection Established!");

            cnn.Close();
        }

        private void displayButton_Click(object sender, EventArgs e)
        {


            string connectionString;
            SqlConnection cnn;

            connectionString = "Server= myServer; Database= nba_database; Integrated Security=True";


            cnn = new SqlConnection(connectionString);

            cnn.Open();
            MessageBox.Show("Connection Established!");

            





           
            // lets query some data from the sql server

            // define variables
            SqlCommand command;
            SqlDataReader dataReader;
            String sql, output = "";

            // define SQL statement!
            sql = "SELECT FirstName, LastName " +
                "FROM Players, Teams " +
                "WHERE Players.TeamID = Teams.TeamID " +
                "AND Teams.Nickname = 'Hawks'";

            String sql2 = "SELECT FirstName, LastName FROM Players WHERE Team = 'Milwaukee Bucks'";

          

            // command statement
            command = new SqlCommand(sql, cnn);
          

            dataReader = command.ExecuteReader();

            // Get table values


            textBox1.Text = command.ExecuteScalar().ToString();


            cnn.Close();
            dataReader.Close();
            command.Dispose();
           
        }

    }
}

我正在尝试将 C# Visual Studio 应用程序连接到 SQL Server 数据库,但出现此错误:System.InvalidOperationException:“已经有一个打开的 DataReader 与此命令关联,必须先关闭。”

当用户单击显示按钮时,我希望能够将查询结果返回到 c# 应用程序中的文本框。

错误在这一行 textBox1.Text = command.ExecuteScalar().ToString();

4

2 回答 2

2

您必须在调用ExecuteScalar ()之前关闭数据读取器。试试看:

        // command statement
        command = new SqlCommand(sql, cnn);
      

        dataReader = command.ExecuteReader();

        // Get table values
        dataReader.Close(); ///<--close reader 

        textBox1.Text = command.ExecuteScalar().ToString();


        cnn.Close();
        
        command.Dispose();
于 2020-07-20T14:45:50.020 回答
2

这是两个重叠的操作;数据读取器在被消耗/关闭/处置之前一直处于活动状态:

// first active operation
dataReader = command.ExecuteReader();

// second active operation
textBox1.Text = command.ExecuteScalar().ToString();

实际上,您没有使用第一个,所以...只需删除该行?

更一般地说:using在所有 ADO.NET 对象上使用是个好主意,坦率地说:ADO.NET API 是一团糟。考虑改用 Dapper,那么这一切就变成了:

string nickname = "Hawks";
using (var cnn = new SqlConnection(connectionString))
{
    textBox1.Text = cnn.ExecuteScalar<string>(@"
SELECT FirstName, LastName
FROM Players, Teams
WHERE Players.TeamID = Teams.TeamID
AND Teams.Nickname = @nickname", new { nickname }");
}

尽管请注意“标量”仅返回一个单元格(第一行的第一列);您可能想对对象做一些事情:

string nickname = "Hawks";
using (var cnn = new SqlConnection(connectionString))
{
    var players = cnn.Query<Player>(@"
SELECT FirstName, LastName
FROM Players, Teams
WHERE Players.TeamID = Teams.TeamID
AND Teams.Nickname = @nickname", new { nickname }).AsList();
}

Player看起来像:

public class Player
{
    public string FirstName {get;set;}
    public string LastName {get;set;}
}
于 2020-07-20T14:46:23.983 回答