尝试向数据库添加新记录时在 C# 中自动生成和自动增量 ID

Auto generate and AutoIncrement ID in C# when trying to add new record to database

我正在使用此代码 select 来自数据库的 maxID table 并且每次我想添加一条新记录时,自动生成的 ID 都不是最后一个 +1。

 public formularAddCompanie()
    {

        InitializeComponent();
        try
        {
            string cs = "Data Source=CODRINMA\CODRINMA;Initial Catalog=TrafficManager;Integrated Security=True";
            string select = "SELECT max(IDCompanie) FROM Companii";

            using (SqlConnection con = new SqlConnection(cs))
            {
                con.Open();
                SqlCommand cmd2 = new SqlCommand(select, con);
                SqlDataReader sda = cmd2.ExecuteReader();
                DataTable idmax = new DataTable("idmax");
                idmax.Load(sda);
                if (idmax.Rows[0][0].ToString().Trim() == "") { txtID.Text = "1"; }
                else { txtID.Text = (int.Parse(idmax.Rows[0][0] .ToString() + 1).ToString()); }
            }
        }
        catch (Exception er) { MessageBox.Show(er.Message); }
    }

制造select离子的table看起来像这样:

IDCompany   Name   Address   City  RegNo
1           A      Street    NY    123

每次我想添加一条新记录时,自动生成的 ID 是这样的:11, 111, 1111。它取最后一个 ID 并在其旁边添加另一个 1。我错过了什么?

idmax.Rows[0][0].ToString() + 1 生成 string,而不是 int

你可以试试

txtID.Text = (Convert.ToInt32(idmax.Rows[0][0]) + 1).ToString();

试试这个片段:

将您的 String 转换为 IntString+ 运算符将 con-cat 并与 int 它将添加数字。

if (idmax.Rows[0][0].ToString().Trim() == "") { txtID.Text = "1"; }

else { 
txtID.Text =  Convert.ToString(Convert.ToInt32(idmax.Rows[0][0] .ToString())+1); }

有趣的是,请注意

string a = "The meaning of life is " + 42;

将 42 转换为字符串,创建结果

a == "The meaning of life is 42"

看这段代码:

(int.Parse(idmax.Rows[0][0] .ToString() + 1).ToString()); }

您正在将 idmax.Rows[0][0] 转换为字符串,并将 +1 添加到字符串 的末尾 而不是整数值。尝试

(int.Parse(idmax.Rows[0][0].ToString()) + 1).ToString(); }

请注意,idmax.Rows[0][0] 中应该已经有一个整数(正如评论中指出的那样)。如果是这样,您可以简化为

(idmax.Rows[0][0] + 1).ToString(); }

我只是添加这个,因为 none 似乎关心发布者发布的代码的弱点。 首先,如果您想查找将分配给 ID 列的下一个自动增量值,则 MAX 函数不可靠。并发可能会对任何使用 MAX 的模式造成严重破坏。假设另一个用户已经为自己的 INSERT 操作检索了 MAX,然后根据两台计算机的相对速度,您或另一个用户将为 IDCompany 字段插入一个重复值。

执行此常见任务的唯一正确方法是对 IDCompany 列使用 IDENTITY 属性,当您需要插入新记录时,您应该这样写

try
{
    string insert  = "INSERT INTO Companii (Name,Address,City,RegNo) 
                      VALUES(@name,@address,@city,@regno);
                      SELECT SCOPE_IDENTITY()";

    using (SqlConnection con = new SqlConnection(cs))
    using (SqlCommand cmd = new SqlCommand(insert, con))
    {
        con.Open();
        cmd.Parameters.Add("@name", SqlDbType.NVarChar).Value = txtBoxCity.Text;
        .... and on for the other parameters ....
        int companyID = Convert.ToInt32(cmd.ExecuteScalar());
        ... work with the just added company if required
    }
}
catch (Exception er) 
{ MessageBox.Show(er.Message); }

SCOPE_IDENTITY 将 return 最后一个标识值插入同一范围内的标识列中,在此上下文范围内表示您的命令使用的连接。

无论如何,如果仍然需要 MAX 方法,那么可以使用修改后的查询和 SqlCommand.ExecuteScalar 来简化代码,而不是构建 SqlDataReader、填充数据表、尝试解析结果如果

string getMax = @"select COALESCE(MAX(IDCompany), 0) + 1 AS maxPlusOne 
                  from Companii"
using(SqlConnection cnn = new SqlConnection(.....))
using(SqlCommand cmd = new SqlCommand(getMax, cnn))
{
    cnn.Open();
    int nextCompanyID = Convert.ToInt32(cmd.ExecuteScalar());
}

The COALESCE function检查MAX函数的结果,如果是NULL returns第二个参数(这里是0),那么只要自增1就可以直接从数据库中得到下一个MAX . ExecuteScalar 将只调用 returning maxPlusOne 别名字段

试试这个,我的 ID 格式是 USR001.The 代码将根据数据库中的最后一个 ID 生成自动 ID。如果数据库中的最后一个 id 是 USR001,代码将生成 USR002 并将 id 放入文本框

con.Open();
            string sqlQuery = "SELECT TOP 1 kode_user from USERADM order by kode_user desc";
            SqlCommand cmd = new SqlCommand(sqlQuery, con);
            SqlDataReader dr = cmd.ExecuteReader();

            while (dr.Read())
            {
                string input = dr["kode_user"].ToString();
                string angka = input.Substring(input.Length - Math.Min(3, input.Length));
                int number = Convert.ToInt32(angka);
                number += 1;
                string str = number.ToString("D3");

                txtKodeUser.Text = "USR" + str;
            }
            con.Close();