2013-06-25 62 views
1

我有一个表单,用户可以插入,查看和更新​​数据。数据插入只完成一次,然后更新可以进行多次。默认情况下,用户将能够查看数据是否存在于数据库中。一次性记录插入然后更新很多次

我试过这个,但它没有插入数据库。然后假设数据库中存在数据,并且当用户想要更新记录时,它会抛出一个错误 - DataReader已打开。

private void display_Emp() 
    { 
     try 
     { 
      using (sqlCon = new SqlConnection(ConfigurationManager.ConnectionStrings["Connection"].ConnectionString)) 
      { 
       sqlCon.Open(); 

       SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM Employee", sqlCon); 
       DataSet ds = new DataSet("Employee"); 
       da.Fill(ds, "Employee"); 
       int x = 0; 
       for (x = 0; x < ds.Tables[0].Rows.Count; x++) 
       { 
        txtID.Text = ds.Tables[0].Rows[x][1].ToString(); 
        txtEmpName.Text = ds.Tables[0].Rows[x][2].ToString(); 
       } 
      } 
     } 
     catch(Exception exx) { 
      MessageBox.Show(exx.Message); 
     } 
     finally { 
      sqlCon.Close(); 
     } 
    } 

private void btnSave_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     using (sqlCon = new SqlConnection(ConfigurationManager.ConnectionStrings["Connection"].ConnectionString)) 
     { 
      sqlCon.Open(); 
      SqlCommand com = new SqlCommand("SELECT * FROM Employee", sqlCon); 

      read = com.ExecuteReader(); 

      while (read.Read()) 
      {      
       if (read.HasRows) 
       { 
        SqlCommand update = new SqlCommand("UPDATE Employee SET EmpID = '" + txtID.Text + "' , EmpName = '" + txtEmpName.Text + "', sqlCon); 
        update.ExecuteNonQuery(); 
        MessageBox.Show("Employee details updated!", "Employee", MessageBoxButtons.OK, MessageBoxIcon.Information); 
       } 
       else 
       { 
        SqlCommand comm = new SqlCommand("INSERT INTO Employee(EmpID, EmpName) VALUES ('" + txtID.Text + "','" + txtEmpName.Text + "')", sqlCon); 
        comm.ExecuteNonQuery(); 
        MessageBox.Show("Employee details saved!", "Employee", MessageBoxButtons.OK, MessageBoxIcon.Information); 
       } 
      } 
     } 
    } 
    catch(Exception ex) 
    { 
     MessageBox.Show(ex.Message); 
    } 
    finally 
    { 
     read.Close(); 
     sqlCon.Close(); 
    }     
} 

编辑:

表: - Deepz(ID INT PK,Goodname VARCHAR(50))

DECLARE @ID int 
DECLARE @Goodname varchar(50) 

    MERGE Deepz t 
    USING (SELECT @ID[ID], @Goodname[Goodname]) s 
     ON (t.ID = s.ID) 
    WHEN MATCHED THEN 
     UPDATE 
     SET t.Goodname = @Goodname 
    WHEN NOT MATCHED THEN 
     INSERT (ID, Goodname) 
     VALUES (@ID, @Goodname); 

错误:

Msg 102, Level 15, State 1, Line 1 
Incorrect syntax near 't'. 
Msg 137, Level 15, State 2, Line 2 
Must declare the scalar variable "@ID". 
+0

迭代! 'datareader'保留连接,因为它是面向连接的方法 –

+5

**警告**:您的代码易受[SQL注入](http://en.wikipedia.org/wiki/SQL_injection)攻击。请使用[SQL参数](http://msdn.microsoft.com/zh-cn/library/system.data.sqlclient.sqlparameter.aspx)。 – Brian

+1

你在哪里声明'read'? – Brian

回答

3

你应该改变你将功能保存到:

  • 如果你的SQL Server 2008或更高版本上,使用SQL Merge语句来插入或更新取决于是否存在记录或不
 
    DECLARE @nameField VarChar(50) = 'some data' 

    MERGE dbo.MyTable t 
    USING (SELECT @nameField [field]) s 
     ON t.myData = s.field 
    WHEN MATCHED THEN 
     UPDATE 
     SET t.myData = @nameField 
    WHEN NOT MATCHED THEN 
     INSERT (myData) 
     VALUES (@nameField); 
  • 如果你的SQL Server 2005或更早上,你需要使用类似于下面的东西,但是你可能会遇到竞争状况(但是imho仍然会比你原来的设计更好,这也有可能导致竞争状况),所以根据你的环境,你可能需要四处游玩带锁等
 
    IF EXISTS (SELECT * FROM Deepz WHERE [ID] = @ID) 
    BEGIN 
     UPDATE Deepz 
     SET Goodname = @Goodname 
     WHERE [ID] = @ID 
    END 
    ELSE 
    BEGIN 
     INSERT Deepz (ID, Goodname) 
     VALUES (@ID, @Goodname); 
    END 
  • 使用SQL PARAMS,而不是通过级联构建的声明,将节省您从SQL injection攻击
 
    UPDATE Employee SET EmpID = @id, EmpName = @name 

然后

 
    SqlCommand comm = new SqlCommand(...); 
    // note below is a bit simplified, in reality you should do int.TryParse 
    comm.Parameters.Add(@id, SqlDbType.Int).Value = int.Parse(txtID.Text); 
+0

之后的顶部声明它从我的代码中,我应该在哪里放置这些SQL合并语句? – deepz

+0

@deepz你应该只需要一个SqlCommand,而且命令本身就是合并语句,就像我在答案中提供的例子。关键是在你的表的唯一约束(帮助你区分一个记录与另一个记录)上合并'USING ... ON ...'部分,然后你只需要将值传递给你的参数,并运行一个SqlCommand会根据存在与否来插入/更新 – Jason

+0

我首先尝试了Sql Server 2005中的合并语句,以测试它是否正常工作。我有一些错误。请看我的编辑。 – deepz

0

这是一个有点拍摄黑暗但是,试试这个:

private void btnSave_Click(object sender, EventArgs e) 
{ 
    try 
    { 
     using (sqlCon = new SqlConnection(ConfigurationManager.ConnectionStrings["Connection"].ConnectionString)) 
     { 
     sqlCon.Open(); 
     SqlCommand com = new SqlCommand("SELECT * FROM Employee", sqlCon); 
     com.Parameters.AddWithValue(@empID, SqlDbType.Int).Value = int.Parse(txtID.Text); // Add this line 
     com.Parameters.AddWithValue(@empName, SqlDbType.NVarChar).Value = txtEmpName.Text; // Add this line too 
     SqlDataReader read = new SqlDataReader(); // You also need to 'new' up your SqlDataReader. 
     read = com.ExecuteReader(); 

     while (read.Read()) 
     {      
      if (read.HasRows) 
      { 
      SqlCommand update = new SqlCommand("UPDATE Employee SET EmpID = @empID, EmpName = @empName", sqlCon); 
      update.ExecuteNonQuery(); 
      MessageBox.Show("Employee details updated!", "Employee", MessageBoxButtons.OK, MessageBoxIcon.Information); 
      } 

      else 
      { 
       SqlCommand comm = new SqlCommand("INSERT INTO Employee(EmpID, EmpName) VALUES (@empID, @empName)", sqlCon); 
       comm.ExecuteNonQuery(); 
       MessageBox.Show("Employee details saved!", "Employee", MessageBoxButtons.OK, MessageBoxIcon.Information); 
      } 
     } 
    } 

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

    finally 
    { 
     read.Close(); 
     sqlCon.Close(); 
    } 
} 
+0

感谢它的工作,但我真正的问题的答案仍然悬而未决。 – deepz