在C#中注入了SQL查询:从数据库中删除记录,然后将记录ID更新为最后一个ID序列

时间:2019-03-27 09:15:31

标签: c# wpf

允许用户删除sql表中的特定记录。问题是我想将id(自动)设置为删除后出现在数据库中的最后一个id序列... ex(删除第14个项目,当我添加另一个项目时,该项目的id不会是15,但是14,因为删除后我将ID重置为13,这是删除后的最后一个)

private void btnCanc_Click(object sender, RoutedEventArgs e)
{


 sqliteCon.Open();
  try
  {
    string Test = null;//estrazione1

    SqlCommand q = new SqlCommand("DELETE FROM tabSE  WHERE idSE =" + txtIDL.Text.ToString(), sqliteCon);
    //string q = "DELETE FROM tabSE  WHERE idSE =" + txtIDL.Text.ToString();

    SqlCommand q1 = new SqlCommand("DELETE FROM tabL  WHERE idL =" + txtIDL.Text.ToString(), sqliteCon);
    //string q1 = "DELETE FROM tabL  WHERE idL =" + txtIDL.Text.ToString();

    SqlCommand q2 = new SqlCommand("DELETE FROM tabSD  WHERE id =" + txtIDL.Text.ToString(), sqliteCon);
    //string q2 = "DELETE FROM tabSD  WHERE id =" + txtIDL.Text.ToString();


    q.ExecuteNonQuery();
    q1.ExecuteNonQuery();
    q2.ExecuteNonQuery();



    SqlCommand m = new SqlCommand("SELECT idL  FROm tabL", sqliteCon);
    SqlDataReader idLRdr = null;//estrazione2
    idLRdr = m.ExecuteReader();//estrazione3
    while (idLRdr.Read())//estrazione4
    {
      Test = idLRdr["idL"].ToString();//estrazione5
    }

    SqlCommand r = new SqlCommand("DBCC CHECKIDENT(tabL,tabSE,tabSD,RESEED,'" + Test + "')", sqliteCon);  
    r.ExecuteNonQuery();

    SqlCommand r1 = new SqlCommand("DBCC CHECKIDENT(tabL,RESEED,'" + Test + "')", sqliteCon);
    r1.ExecuteNonQuery();
    SqlCommand r2 = new SqlCommand("DBCC CHECKIDENT(tabSE,RESEED,'" + Test + "')", sqliteCon);
    r2.ExecuteNonQuery();
    SqlCommand r3 = new SqlCommand("DBCC CHECKIDENT(tabSD,RESEED,'" + Test + "')", sqliteCon);
    r3.ExecuteNonQuery();
  }
  catch (SqlException ex)
  {
    MessageBox.Show(ex.Message);
  }
  MessageBox.Show("Dato Cancellato Correttamente");
  sqliteCon.Close();

}

代码已改进,但它更新了表ID的值,但未更新每个表的真实ID(idL,idSE,id)(这些是我的自定义ID)

好的,我已经做了我的测试,问题是每个表的ID(idL(TABLE tabL),idSE(TABLE tabSE),id(TABLE tabSD))都没有被我的代码DBCC更新每个表(不需要定制的表)都是自动更新的...我需要更新idL,idSE,id

2 个答案:

答案 0 :(得分:3)

当然,第一个问题是您不执行命令,但是代码中有很多可以改进的地方。首先是构建sql命令的字符串连接。这会导致解析问题以及用于入侵数据库的dangerous Sql Injection技巧。我已更改您的代码以使用参数并避免出现这些问题。

第二个改进是执行批处理命令的能力。换句话说,您可以将所有命令文本放在单个字符串中,并使用分号将每个命令文本分开。然后只执行一次命令,一切将由数据库引擎执行。

但是代码中真正的问题是 DBCC CheckIdentity RESEED 部分。这部分要求您知道将哪个值设置为新标识,因为没有下一个新值的RESEED选项仅在下一个标识值低于IDENTITY列中的当前最大值时才起作用,此外,只有当您拥有对数据库的独占访问权限(我的意思是,在您获得ID的最大值时,没有人向这些表添加记录)

sqliteCon.Open();
try
{
    string sqlText = @"DELETE FROM tabStoreExec  WHERE idSE = @idse;
                       DELETE FROM tabList  WHERE idL = @idse;
                       DELETE FROM tabStoricoDetail  WHERE id = @idse";
   SqlCommand q = new SqlCommand(sqlText, sqliteCon);
   q.Parameters.Add("@idse", SqlDbType.Int).Value = Convert.ToInt32(txtIDL.Text);
   q.ExecuteNonQuery();


   // This is the point where you change the identity.
   // To minimize concurrency problems we execute a stored procedure instead 
   sqlText = "ResetIdentity";
   q.CommandText = sqlText;
   q.CommandType = CommandType.StoredProcedure;
   q.Parameters.Clear();
   q.ExecuteNonQuery();
   MessageBox.Show("Dato Cancellato Correttamente");
}
catch (SqlException ex)
{
   MessageBox.Show(ex.Message);
}
sqliteCon.Close();

这是存储过程的可能代码,请注意,我不知道表中IDENTITY列的名称是什么。在此示例中,我始终使用 id 作为IDENTITY列的名称

create procedure ResetIdentity
as
    begin
    declare @maxval integer

    set @maxval = (select MAX(id) from tabStoreExec);
    dbcc checkident('tabStoreExec', RESEED, @maxval);

    set @maxval = (select MAX(id) from tabStoricoDetail);
    dbcc checkident('tabStoricoDetail', RESEED, @maxval);

    set @maxval = (select MAX(id) from tabList);
    dbcc checkident('tabList', RESEED, @maxval);
end 

您的代码还有另一个改进,它与using statement有关,它可以创建一次性对象,例如数据库连接。此类对象的正确用法应该是这样

using(SqlConnection sqlConn = new SqlConnection(......))
{
     sqlConn.Open();
     .... do you database code here ....
} // This will close and dispose the connection

答案 1 :(得分:0)

我也将按照@Steve所说的去做,这里的ID是用于表(PK,FK)关系的,为什么不只是添加另一个需要使用LINQ更新的序号字段。并且您的代码缺少查询执行命令,

#include <iostream>

int main() {

    const float v1 = 0.499999975;
    const float v2 = 0.4999999702;

    std::cout << (int)(v1+0.5) << "\n" 
              << (int)(v2+0.5) << "\n";
}

con.Close();