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