Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何生成每年重置的自动递增ID号_C#_Sql_Sql Server_Tsql - Fatal编程技术网

C# 如何生成每年重置的自动递增ID号

C# 如何生成每年重置的自动递增ID号,c#,sql,sql-server,tsql,C#,Sql,Sql Server,Tsql,我有一个基于年份生成学生ID的应用程序,如第一个ID: 202100001,然后是202100002,依此类推。基本上需要一年,然后开始增加计数器 这很好也很简单,但我的问题是,它从数据库中获取最后一个ID来生成学生ID。 当有新的一年时,年份部分会发生变化,但不会重置为零。 我想在2022年开始:202200001年,然后202200002年,依此类推。 是否有更简单的方法重置计数器,我是否应该为此添加一个新列 这是我当前的代码: //Generate Student Number strin

我有一个基于年份生成学生ID的应用程序,如第一个ID: 202100001,然后是202100002,依此类推。基本上需要一年,然后开始增加计数器

这很好也很简单,但我的问题是,它从数据库中获取最后一个ID来生成学生ID。 当有新的一年时,年份部分会发生变化,但不会重置为零。 我想在2022年开始:202200001年,然后202200002年,依此类推。 是否有更简单的方法重置计数器,我是否应该为此添加一个新列

这是我当前的代码:

//Generate Student Number
string StudentNumber;
private void GenerateStudentNumber()
{
    DateTime moment = DateTime.Now;
    string year = moment.Year.ToString();
    try
    {
        StudentNumber = GenerateID();               
        txtStudentNumber.Text = year + StudentNumber;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

private string GenerateID()
{    
    string value = "00";
    int IDindex = 0;
    try
    {        
        using (con = new SqlConnection(databaseConnectionString))
        {
            // Fetch the latest ID from the database
            con.Open();
            cmd = new SqlCommand("SELECT TOP 1 StudentID FROM Students order BY StudentID DESC", con);
            rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
            if (rdr.HasRows)
            {
                rdr.Read();
                IDindex = Convert.ToInt16(rdr["StudentID"]);
            }
            rdr.Close();
        }
            
        IDindex++;
        // Because incrementing a string with an integer removes 0's
        // we need to replace them. If necessary.
        if (IDindex <= 9)
        {
            value = "00" + value + IDindex.ToString();
        }
        else if (IDindex <= 99)
        {
            value = "0" + value + IDindex.ToString();
        }
        else if (IDindex <= 999)
        {
            //value = "00" + value + IDindex.ToString();
            value = value + IDindex.ToString();
        }
        else if (IDindex <= 9999)
        {
            value = "0" + IDindex.ToString();
        }        
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    return value;
}

非常感谢。

我的建议是设置一个序列:

 CREATE SEQUENCE StudentSequenceWithinYear;
您可以每年运行一次作业来重置该值:

ALTER SEQUENCE StudentSequenceWithinYear RESTART WITH 1 ;  
您可以将其自动设置为12月31日/1月1日午夜左右运行

然后在
CREATE TABLE
语句中,您可以使用:

CREATE TABLE Students (
    StudentID  INT IDENTITY (1, 1) NOT NULL,
    StudentNumber NVARCHAR (50) NOT NULL,
    Year INT DEFAULT YEAR(GETDATE()),
    WithinYearSequence INT DEFAULT NEXT VALUE FOR StudentSequenceWithinYear,
    MyStudentId AS (CONCAT(Year, FORMAT(WithinYearSequence, '00000'))) 
);

综上所述,我认为你应该使用一个身份栏来识别学生。试图在id中存储信息通常会导致边缘案例出现问题(例如,一名学生一年退学一年,但又返回另一年)。您可以随时在数据库中查找年份,因此不需要将其作为id的一部分存储。

“但我的问题是,从数据库中获取最后一个id来生成学生id”问题不仅在于您需要每年生成一次,而且在于您的代码生成了它。这只是数据库的一项任务,该数据库也负责ID。否则,这是一个竞争条件,您的应用程序迟早会丢失。大多数数据库(包括SQL Server)都有一个可用于此的类型。这听起来像是您应该使用行数计算并按年份分区的数据。何时重置序列?基于什么标准?如果使用当前时间,使用序列会容易得多,请将
StudentNumber
的默认值设置为
StudentCounter
的下一个值,并每年重置一次。由于您谈论的是学生ID,“年”无论如何都不会是日历年顺便说一句,您的整个if块可以替换为
IDIndex.ToString(“00000”)
的一些调整。不要使用PascalCase命名局部变量;使用Camelcase谢谢Gordon。我以前没有使用过sequence,但这个选项似乎可以在我的应用程序中使用。我会研究你的建议。
CREATE TABLE Students (
    StudentID  INT IDENTITY (1, 1) NOT NULL,
    StudentNumber NVARCHAR (50) NOT NULL,
    Year INT DEFAULT YEAR(GETDATE()),
    WithinYearSequence INT DEFAULT NEXT VALUE FOR StudentSequenceWithinYear,
    MyStudentId AS (CONCAT(Year, FORMAT(WithinYearSequence, '00000'))) 
);