无法从C#中的SqlDataReader检索数据

时间:2015-05-08 11:35:30

标签: c# sql sql-server

我需要先将值插入到几个表中,然后我必须从表学院中检索大学ID,然后将教师名称插入到表教员中并由SQL Server ID生成。完成所有这些后,我必须将两个ID插入另一个表中。

问题是我必须关闭读者,在我这样做之后,我无法从它们中检索这些ID,因此应该保存它们的变量为null。这是我的代码。怎么做正确?

抱歉,我是C#和SQL Server的新手。

// reading data into combobox 
try
{
    SqlDataReader myReader = null;
    SqlCommand myCommand = new SqlCommand("select * from colege", myConnection);

    myReader = myCommand.ExecuteReader();

    while (myReader.Read())
    {
        comboBox1.Items.Add(myReader["name"].ToString());
        // Console.WriteLine(myReader["Column2"].ToString());
    }
}
catch (Exception ex)
{
    Console.WriteLine(ex.ToString());
}

myConnection.Close();

private void button1_Click(object sender, EventArgs e)
{
    string item = comboBox1.Text.ToString();
    // MessageBox.Show(item);
    SqlConnection myConnection = new SqlConnection("user id=bogdan_db;" +
                                       "password=1234;server=localhost;" +
                                       "Trusted_Connection=yes;" +
                                       "database=cafedrascience; " +
                                       "connection timeout=30");

    try
    {
        myConnection.Open();
    }
    catch (Exception E)
    {
        Console.WriteLine(E.ToString());
    }

    // reading data into combobox 
    String colegeid = null;

    try
    {
        SqlDataReader myReader = null;

        SqlCommand myCommand = new SqlCommand("select * from colege where name like'" + item + "'", myConnection);

        myReader = myCommand.ExecuteReader();

        while (myReader.Read())
        {
            colegeid = myReader["id"].ToString();
            // Console.WriteLine(myReader["Column2"].ToString());
        }

        myReader.Close();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }

    String facultyid = null;
            try
            {
                SqlDataReader myReader1 = null;
                SqlCommand myCommand = new SqlCommand("select * from depart where name like'" + textBox1.Text + "'",
                                                         myConnection);
                myReader1 = myCommand.ExecuteReader();
                while (myReader1.Read())
                {

                    facultyid = myReader1["id"].ToString();
                }
                myReader1.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
            SqlCommand myCommand1 = new SqlCommand("INSERT INTO coledge_faculty (coledge_id, faculty_id) " +
                                               "Values ('"+colegeid+"''"+facultyid+"')", myConnection);
           myCommand1.ExecuteNonQuery();
           // MessageBox.Show(colegeid);
           // MessageBox.Show(facultyid);
            myConnection.Close();

        }

2 个答案:

答案 0 :(得分:3)

我可以强调你的代码最重要的一点是你应该使用parameterised queries,除了SQL注入的明显风险之外,它还可以保护你免受格式错误的SQL,通过转换截断数据,并且它允许你使用缓存的执行计划。

接下来要指出的是should not be using SELECT * in production code,例如

    SqlCommand myCommand = new SqlCommand("select * from colege where name like'" + item + "'",
                                                myConnection);
    myReader = myCommand.ExecuteReader();
    while (myReader.Read())
    {

        colegeid = myReader["id"].ToString();
        //    Console.WriteLine(myReader["Column2"].ToString());
    }

为什么还要从数据库中检索colege的所有列,如果您只关心列id,则通过网络发送它们?

最后你对问题的诊断不正确:

  

问题是我必须关闭读者,在我这样做之后,我无法从这些读者那里撤回这些ID,因此应该保存它们的变量为null

如果为字符串变量colegeid分配了一个从数据读取器中读取的值,则在关闭阅读器后它不会为空,它将保留您指定的值。变量为null的最可能原因是因为您的读者不返回任何行,因此您永远不会为其赋值。

现在,咆哮,我会实际回答你的问题。您大大超过了问题的复杂性,您不需要将值检索到应用程序层只是为了将它们插入到另一个表中,您可以在数据库中的单个查询中执行此操作:

INSERT INTO coledge_faculty (coledge_id, faculty_id)
SELECT  c.id, d.id
FROM    depart AS d
        CROSS JOIN colege AS c
WHERE   d.Name = @Depart
AND     c.Name = @Colege;

然后它只是从c#:

调用此SQL的情况
string item = comboBox1.Text.ToString();
string connectionString = "user id=bogdan_db; password=1234;server=localhost; Trusted_Connection=yes; database=cafedrascience; connection timeout=30";
string sql = @"INSERT INTO coledge_faculty (coledge_id, faculty_id)
                SELECT  c.id, d.id
                FROM    depart AS d
                        CROSS JOIN colege AS c
                WHERE   d.Name = @Depart
                AND     c.Name = @Colege;";

using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand(sql, connection))
{
    command.Parameters.Add("@Colege", SqlDbType.VarChar, 50).Value = item;
    command.Parameters.Add("@Depart", SqlDbType.VarChar, 50).Value = textBox1.Text;
    connection.Open();
    command.ExecuteNonQuery();
}

using块与实现IDisposable的对象一起使用通常是一个好主意,这样可以确保在完成这些操作后释放资源(不要将此与之混淆)由于无法重用连接,.NET在后台有连接池,所以它会为你重用连接,你不应该保持你的SqlConnection对象可用,以防你需要再次使用它。)

在另一个不相关的说明中,我也认为你对try / catch块过于自由,或者至少没有正确处理异常,以此为例:

try
{
    myConnection.Open();
}
catch (Exception E)
{
    Console.WriteLine(E.ToString());

}

如果myConnection.Open()确实抛出错误,您仍然继续使用该方法。你会继续,直到你到达这里:

SqlCommand myCommand = new SqlCommand("select * from colege where name like'" + item + "'",
                                                myConnection);
myReader = myCommand.ExecuteReader();

你会得到另一个例外,这个命令需要一个开放且可用的Sql连接,所以你去了例外。

catch (Exception ex)
{
    MessageBox.Show(ex.ToString());
}

同样,您不会退出该方法,但继续操作,稍后当您尝试再次使用该连接时,您将收到相同的错误。该方法再次继续,您将第三次使用已关闭的连接尝试插入两个从未分配的变量,因为异常被抛入您的数据库。好的,使用try catch块,但是对异常执行一些有意义的操作并退出方法。

答案 1 :(得分:-1)

 private void BtnAdd_Click(object sender, EventArgs e)
    {
        //con.Open();
        cmd = new SqlCommand("INSERT INTO TBL_STORE VALUES (N'"+txt_store_name.Text.Trim()+"',N'"+txt_store_adress.Text.Trim()+"',N'"+txt_store_mobile_1.Text.Trim()+"',N'"+txt_store_mobile_2.Text.Trim()+"',N'"+txt_store_Manger.Text.Trim()+"',N'"+txt_store_Details.Text.Trim()+"')");
        cmd.Connection = con;
        cmd.ExecuteNonQuery();

            cmd.Parameters.AddWithValue("@store_name", txt_store_name.Text.Trim());
            cmd.Parameters.AddWithValue("@store_adress", txt_store_adress.Text.Trim());
            cmd.Parameters.AddWithValue("@store_mobile_1", txt_store_mobile_1.Text.Trim());
            cmd.Parameters.AddWithValue("@store_mobile_2", txt_store_mobile_2.Text.Trim());
            cmd.Parameters.AddWithValue("@store_manger", txt_store_Manger.Text.Trim());
            cmd.Parameters.AddWithValue("@store_details", txt_store_Details.Text.Trim());
            cmd.Parameters.AddWithValue("@Id_store", txt_store_number.Text.Trim());

        con.Close();
        lbl_store.Text="insert is sucess";

        //cmd.Parameters.Add("@store_name", SqlDbType.NVarChar, 50).Value = txt_store_name.Text.Trim();
    }