From 05a7cc3e9bdb4a38b8d56008c45192eb36756386 Mon Sep 17 00:00:00 2001 From: yiming Date: Wed, 10 Sep 2025 00:21:47 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E5=AF=AB=E4=BF=A1=E7=9C=BE=E7=B7=A8?= =?UTF-8?q?=E8=99=9F=E7=A8=8B=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/App_Code/GlobalVariables.cs | 2 +- web/App_Code/Model/Partial/follower.cs | 86 +++++++++++++++++++++++--- web/Global.asax | 36 ----------- web/admin/follower/reg.aspx.cs | 19 +----- 4 files changed, 78 insertions(+), 65 deletions(-) diff --git a/web/App_Code/GlobalVariables.cs b/web/App_Code/GlobalVariables.cs index 00125d9..8dd99f3 100644 --- a/web/App_Code/GlobalVariables.cs +++ b/web/App_Code/GlobalVariables.cs @@ -8,5 +8,5 @@ using System.Web; /// public static class GlobalVariables { - public static readonly object FNumberLock = new object(); + // FNumberLock 已移除,因為改用資料庫直接取號,不再需要 Application 狀態鎖定 } \ No newline at end of file diff --git a/web/App_Code/Model/Partial/follower.cs b/web/App_Code/Model/Partial/follower.cs index 4417537..964fbe6 100644 --- a/web/App_Code/Model/Partial/follower.cs +++ b/web/App_Code/Model/Partial/follower.cs @@ -190,20 +190,86 @@ namespace Model public static string generate_f_number(string sex = "男眾") { string selectedSex = sex; - string f_number = selectedSex == "男眾" ? "M" : "F"; var datePart = DateTime.Now.ToString("yyyyMMdd"); - f_number += datePart; - - - int nextSerial = 1; - lock (GlobalVariables.FNumberLock) + // 使用重試機制確保不重號 + int maxRetries = 5; + for (int retry = 0; retry < maxRetries; retry++) { - nextSerial = (int)HttpContext.Current.Application["FNumberSerial"] + 1; - HttpContext.Current.Application["FNumberSerial"] = nextSerial; + try + { + using (var _db = new Model.ezEntities()) + using (var transaction = _db.Database.BeginTransaction()) + { + // 在交易中查詢最大序號 + int nextSerial = GetNextSerialFromDatabase(_db, datePart, selectedSex); + string f_number = GenerateFNumber(selectedSex, datePart, nextSerial); + + // 立即檢查是否重複(在交易中) + if (!_db.followers.Any(f => f.f_number == f_number)) + { + transaction.Commit(); + return f_number; + } + + // 如果重複,回滾交易並重試 + transaction.Rollback(); + + // 短暫延遲後重試 + if (retry < maxRetries - 1) + { + System.Threading.Thread.Sleep(10 + retry * 5); // 10ms, 15ms, 20ms, 25ms + } + } + } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"生成編號失敗 (重試 {retry + 1}): {ex.Message}"); + if (retry == maxRetries - 1) + { + // 最後一次重試失敗,使用時間戳記確保唯一性 + return GenerateFNumberWithTimestamp(selectedSex, datePart); + } + } } - f_number += nextSerial.ToString("D5"); - return f_number; + + // 如果所有重試都失敗,使用時間戳記 + return GenerateFNumberWithTimestamp(selectedSex, datePart); + } + + private static int GetNextSerialFromDatabase(Model.ezEntities _db, string datePart, string sex) + { + var prefix = sex == "男眾" ? "M" : "F"; + var searchPattern = prefix + datePart; + + var maxFNumber = _db.followers + .Where(m => + m.f_number.Length == 14 && + m.f_number.StartsWith(searchPattern)) + .OrderByDescending(m => m.f_number) + .Select(m => m.f_number) + .FirstOrDefault(); + + if (!string.IsNullOrEmpty(maxFNumber)) + { + var serialPart = maxFNumber.Substring(9, 5); + return int.Parse(serialPart) + 1; + } + return 1; + } + + private static string GenerateFNumber(string sex, string datePart, int serial) + { + string prefix = sex == "男眾" ? "M" : "F"; + return prefix + datePart + serial.ToString("D5"); + } + + private static string GenerateFNumberWithTimestamp(string sex, string datePart) + { + // 使用時間戳記確保唯一性(最後手段) + string prefix = sex == "男眾" ? "M" : "F"; + var timestamp = DateTime.Now.ToString("HHmmss"); + return prefix + datePart + timestamp; } } diff --git a/web/Global.asax b/web/Global.asax index 381a255..fad990f 100644 --- a/web/Global.asax +++ b/web/Global.asax @@ -27,8 +27,6 @@ //GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear(); //註冊自訂路由 RouteConfig.RegisterRoutes(RouteTable.Routes); - InitializeFNumberSerial();//啟動項目的時候查詢出信眾編號的最大值放在記憶體中 - //bundle js、css //BundleConfig.RegisterBundles(BundleTable.Bundles); @@ -63,38 +61,4 @@ System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required); } - private void InitializeFNumberSerial() - { - try - { - using (var _db = new Model.ezEntities()) - { - var maxFNumber = _db.followers - .Where(m => - ////m.IsDel == false && ////不確定是否新增欄位? 先註解 - m.f_number.Length == 14 && - (m.f_number.StartsWith("M") || m.f_number.StartsWith("F"))) - .OrderByDescending(m => m.reg_time) - .Select(m => m.f_number) - .FirstOrDefault(); - - int nextSerial = 0; - if (!string.IsNullOrEmpty(maxFNumber)) - { - try - { - var serialPart = maxFNumber.Substring(9, 5); - nextSerial = int.Parse(serialPart); - } - catch { } - } - - Application["FNumberSerial"] = nextSerial; - } - } - catch (Exception ex) - { - Application["FNumberSerial"] = 0; - } - } diff --git a/web/admin/follower/reg.aspx.cs b/web/admin/follower/reg.aspx.cs index c56fd5d..77e7971 100644 --- a/web/admin/follower/reg.aspx.cs +++ b/web/admin/follower/reg.aspx.cs @@ -207,25 +207,8 @@ public partial class admin_follower_reg : MyWeb.config } } } + // 使用新的 generate_f_number 方法,已內建重號檢查和重試機制 followers.f_number = follower.generate_f_number(sex.SelectedValue); - if (chk_pro_num(followers.f_number)) - { - - } - else - { - followers.f_number = follower.generate_f_number(sex.SelectedValue); - if (chk_pro_num(followers.f_number)) - { - - } - else - { - L_msg.Type = alert_type.danger; - L_msg.Text = "信眾編號重複"; - return; - } - } followers.identity_type = Val(identity_type.SelectedValue); if(!isStrNull(leader.Value)) followers.leader = Val(leader.Value); if (!isStrNull(country.Value)) followers.country = country.Value;