如何实现不重复的用户自动生成参考编号?
解决自动参考编号重复问题
你的代码存在几个核心问题导致编号重复,以下是问题分析和修复方案:
问题点
Random实例滥用
每次生成字符时都新建Random实例,短时间内多次创建会因为系统时钟种子相同,生成完全重复的随机序列,这是编号重复的主要原因。数据库检查逻辑完全失效
查询数据库时,ReferenceLabel.Text还未赋值,参数为空,永远查不到已存在的编号;即使查到重复,代码也没有任何处理逻辑。Session去重无意义
Session是单用户会话级存储,无法跨用户、跨会话保证全局唯一,重启应用后数据全部丢失,完全起不到全局去重作用。未处理重复生成的情况
如果生成的编号在Session列表中存在,代码没有重新生成新编号,导致标签可能无值。
修复方案
1. 修正随机数生成逻辑
使用静态Random实例,避免重复种子问题。如果不需要编号内字符唯一(原代码的do-while逻辑强制字符不重复,会大幅缩小编号空间),可以简化生成逻辑:
// 在类级别声明静态Random,确保整个应用生命周期内只初始化一次 private static readonly Random _random = new Random(); private string GetAutoNumber() { string digits = "0123456789"; int length = 9; char[] resultChars = new char[length]; for (int i = 0; i < length; i++) { // 使用静态Random实例生成索引 int index = _random.Next(digits.Length); resultChars[i] = digits[index]; } return new string(resultChars); }
如果确实需要编号内字符不重复(比如避免同一编号内出现相同数字),可以保留去重逻辑,但仍要使用静态Random:
private static readonly Random _random = new Random(); private string GetAutoNumber() { List<char> availableDigits = "0123456789".ToList(); int length = 9; char[] resultChars = new char[length]; for (int i = 0; i < length; i++) { int index = _random.Next(availableDigits.Count); resultChars[i] = availableDigits[index]; // 移除已使用的字符,避免重复 availableDigits.RemoveAt(index); } return new string(resultChars); }
2. 重构编号生成与检查逻辑
直接以数据库为唯一权威数据源,循环生成编号直到找到不存在的:
protected void Page_Load(object sender, EventArgs e) { if (!this.IsPostBack) { AutoGenerateNumber(); } } private void AutoGenerateNumber() { string uniqueNumber = null; bool isDuplicate; using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConString"].ConnectionString)) { con.Open(); do { // 生成新编号 uniqueNumber = GetAutoNumber(); // 检查数据库中是否存在该编号 using (SqlCommand checkCmd = new SqlCommand("SELECT COUNT(1) FROM IDTable WHERE reference_no = @reference_no", con)) { checkCmd.Parameters.AddWithValue("@reference_no", uniqueNumber); // ExecuteScalar返回匹配行数,大于0表示已存在 isDuplicate = (int)checkCmd.ExecuteScalar() > 0; } } while (isDuplicate); // 重复就重新生成 // 赋值到标签 ReferenceLabel.Text = uniqueNumber; } }
3. 可选优化方案
如果需要更高性能或完全避免重复风险,可以改用自增ID+固定格式的方式:
- 在数据库表中添加自增整数列(比如
id INT IDENTITY(1,1)) - 生成编号时使用
"REF" + id.ToString("D9")(D9表示补零到9位,比如id=123时生成REF000000123)
这种方式完全不需要随机生成和重复检查,性能和可靠性都更高。
内容的提问来源于stack exchange,提问作者Donald
相关产品推荐
相关产品推荐

