专业编程基础技术教程

网站首页 > 基础教程 正文

「分享」C#如何生成短订单编号

ccvgpt 2024-08-18 14:27:37 基础教程 7 ℃

订单编号一个重要需求是避免重复,还有是尽量短,利于用户输入,以下分享一个C#编写的类,使用时用单例模式,或者设置全局静态变量。上代码吧

public class OrderCodeGenerator : IDisposable
    {
        Dictionary<string, Queue<string>> orderNosByDay = new();
        int Lenght;
        public OrderCodeGenerator(int lenght)
        {
            //号码池规模与Lenght相关,等于10的lenght次方,在Init()中体现
            Lenght = lenght;
            Recover();
        }
        /// <summary>
        /// 生成订正式订单编号
        /// </summary>
        /// <param name="prefix">自定义前缀</param>
        /// <returns></returns>
        public string Generate(string prefix="")
        {
            var key = GetKey();
            //日期部分,避免重估
            var dayPart = DateTime.Now.ToString("yyyyMMdd");
            var code = "";
            lock (orderNosByDay)
            {
                if (!orderNosByDay.ContainsKey(key))
                {
                    Recover();
                }
                code = prefix + dayPart + orderNosByDay[key].Dequeue();
            }
            Persist();
            return code;
        }
        string GetFilePath()
        {
            var dir = Path.Combine(Environment.CurrentDirectory, "temp");
            
            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }
            var key = GetKey();
            return Path.Combine(dir, key + ".txt");
        }
        string GetKey()
        {
            return DateTime.Now.ToString("yyyyMMdd");
        }
        /// <summary>
        /// 持久化到文件
        /// </summary>
        void Persist()
        {
            var key = GetKey();
            using (var fs = File.CreateText(GetFilePath()))
            {
                if (orderNosByDay.ContainsKey(key))
                {
                    foreach (var item in orderNosByDay[key])
                    {
                        fs.WriteLine(item);
                    }
                }

            }
        }
        /// <summary>
        /// 从持久化文件恢复,如果没有则初始化
        /// </summary>
        void Recover()
        {
            var filePath = GetFilePath();
            var key = GetKey();
            var _queue = new Queue<string>();
            if (File.Exists(filePath))
            {
                using (var fs = File.OpenText(filePath))
                {
                    string line = "";
                    while (!string.IsNullOrEmpty(line = fs.ReadLine()))
                    {
                        _queue.Enqueue(line?.Trim());
                    }
                    orderNosByDay[key] = _queue;
                }
            }
            else
            {
                Init();
                Persist();
            }
        }

        /// <summary>
        /// 初始化无重复订单号码池并打乱顺序
        /// </summary>
        void Init()
        {
            var size = (int)Math.Pow(10, Lenght);
            var numbers = new List<string>();
            for (int i = 0; i < size; i++)
            {
                numbers.Add(i.ToString().PadLeft(Lenght, '0'));
            }

            var key = GetKey();
            orderNosByDay[key] = new Queue<string>();
            Random r = new Random();
            while (numbers.Count > 0)
            {
                var index = r.Next(0, numbers.Count);
                var n = numbers[index];
                orderNosByDay[key].Enqueue(n);
                numbers.RemoveAt(index);
            }
        }

        public void Dispose()
        {
            Persist();
        }
    }

使用

「分享」C#如何生成短订单编号

static OrderCodeGenerator genrator = new OrderCodeGenerator(4);
string NewOrderId(string prefix="")
        {
            
            string orderCode = genrator.Generate(prefix);
            return orderCode;
        }

lenght=4,保证每日有1w个号码可用,如果想要号码池更大,加大lenght即可。

持久化方式其实可以有多种方式,数据库,redis等等。

Tags:

最近发表
标签列表