生成唯一值的方法很多,下面就不同环境下生成的唯一标识方法一一介绍,作为工作中的一次总结,有兴趣的可以自行测试:


一、在 .NET 中生成


1、直接用.NET Framework 提供的 Guid() 函数,此种方法使用非常广泛。GUID(全局统一标识符)是指在一台机器上生成的数字,它保证对在同一时空中的任何两台计算机都不会生成重复的 GUID 值(即保证所有机器都是唯一的)。关于GUID的介绍在此不作具体熬述,想深入了解可以自行查阅MSDN。代码如下:


代码 复制 - 运行

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string _guid = GetGuid();
            Console.WriteLine("唯一码:{0}\t长度为:{1}\n去掉连接符:{2}", _guid, _guid.Length, _guid.Replace("-", ""));
            string uniqueIdString = GuidTo16String();
            Console.WriteLine("唯一码:{0}\t长度为:{1}", uniqueIdString, uniqueIdString.Length);
            long uniqueIdLong = GuidToLongID();
            Console.WriteLine("唯一码:{0}\t长度为:{1}", uniqueIdLong, uniqueIdLong.ToString().Length);
        }
        /// <summary>
        /// 由连字符分隔的32位数字
        /// </summary>
        /// <returns></returns>
        private static string GetGuid()
        {
            System.Guid guid = new Guid();
            guid = Guid.NewGuid();
            return guid.ToString();
        }
        /// <summary>  
        /// 根据GUID获取16位的唯一字符串  
        /// </summary>  
        /// <param name=\"guid\"></param>  
        /// <returns></returns>  
        public static string GuidTo16String()
        {
            long i = 1;
            foreach (byte b in Guid.NewGuid().ToByteArray())
                i *= ((int)b + 1);
            return string.Format("{0:x}", i - DateTime.Now.Ticks);
        }
        /// <summary>  
        /// 根据GUID获取19位的唯一数字序列  
        /// </summary>  
        /// <returns></returns>  
        public static long GuidToLongID()
        {
            byte[] buffer = Guid.NewGuid().ToByteArray();
            return BitConverter.ToInt64(buffer, 0);
        }   
    }
}



2、用 DateTime.Now.ToString("yyyyMMddHHmmssms") 和 .NET Framework 提供的 RNGCryptoServiceProvider() 结合生成,代码如下:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace ConsoleApplication1
{
   class Program
   {
       static void Main(string[] args)
       {
           string uniqueNum = GenerateOrderNumber();
           Console.WriteLine("唯一码:{0}\t 长度为:{1}", uniqueNum, uniqueNum.Length);
           //测试是否会生成重复
             Console.WriteLine("时间+RNGCryptoServiceProvider()结合生成的唯一值,如下:");
           string _tempNum = string.Empty;
           for (int i = 0; i < 1000; i++)
           {
               string uNum = GenerateOrderNumber();
               Console.WriteLine(uNum);
               if (string.Equals(uNum, _tempNum))
               {
                   Console.WriteLine("上值存在重复,按Enter键继续");
                   Console.ReadKey();
               }
               //Sleep当前线程,是为了延时,从而不产生重复值。可以把它注释掉测试看
               Thread.Sleep(300);
               _tempNum = uNum;
           }
       }
       /// <summary>
       /// 唯一订单号生成
       /// </summary>
       /// <returns></returns>
       public static string GenerateOrderNumber()
       {
           string strDateTimeNumber = DateTime.Now.ToString("yyyyMMddHHmmssms");
           string strRandomResult = NextRandom(1000, 1).ToString();
           return strDateTimeNumber + strRandomResult;
       }
       /// <summary>
       /// 参考:msdn上的RNGCryptoServiceProvider例子
       /// </summary>
       /// <param name="numSeeds"></param>
       /// <param name="length"></param>
       /// <returns></returns>
       private static int NextRandom(int numSeeds, int length)
       {
           // Create a byte array to hold the random value.  
           byte[] randomNumber = new byte[length];
           // Create a new instance of the RNGCryptoServiceProvider.  
           System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
           // Fill the array with a random value.  
           rng.GetBytes(randomNumber);
           // Convert the byte to an uint value to make the modulus operation easier.  
           uint randomResult = 0x0;
           for (int i = 0; i < length; i++)
           {
               randomResult |= ((uint)randomNumber[i] << ((length - 1 - i) * 8));
           }
           return (int)(randomResult % numSeeds) + 1;
       }
   }
}



3、用 [0-9A-Z] + Guid.NewGuid() 结合生成特定位数的唯一字符串,代码如下:


代码 复制 - 运行

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{ 
    class Program
    {
        static void Main(string[] args)
        {
            string uniqueText = GenerateUniqueText(8);
            Console.WriteLine("唯一码:{0}\t 长度为:{1}", uniqueText, uniqueText.Length);
            //测试是否会生成重复 
              Console.WriteLine("由[0-9A-Z] + NewGuid() 结合生成的唯一值,如下:");
            IList<string> list = new List<string>();
            for (int i = 1; i <= 1000; i++)
            {
                string _uT = GenerateUniqueText(8);
                Console.WriteLine("{0}\t{1}", list.Count, _uT);
                if (list.Contains(_uT))
                {
                    Console.WriteLine("{0}值存在重复", _uT);
                    Console.ReadKey();
                }
                list.Add(_uT);
                //if (i % 200 == 0)
                //{
                    //Console.WriteLine("没有重复,按Enter键往下看");
                    //Console.ReadKey();
                //}
            }
            list.Clear();
        }

        /// <summary>
        /// 生成特定位数的唯一字符串
        /// </summary>
        /// <param name="num">特定位数</param>
        /// <returns></returns>
        public static string GenerateUniqueText(int num)
        {
            string randomResult = string.Empty;
            string readyStr = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
            char[] rtn = new char[num];
            Guid gid = Guid.NewGuid();
            var ba = gid.ToByteArray();
            for (var i = 0; i < num; i++)
            {
                rtn[i] = readyStr[((ba[i] + ba[num + i]) % 35)];
            }
            foreach (char r in rtn)
            {
                randomResult += r;
            }
            return randomResult;
        }
    }
}



4、用单例模式实现,由[0-9a-z]组合生成的唯一值,此文不讨论单例模式的多种实现方式与性能问题,随便弄一种方式实现,代码如下:


Demo结构如图:
您是游客您没有权限查看该图片



Program.cs 程序:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Xml;
namespace ConsoleApplication4
{
   class Program
   {
       static void Main(string[] args)
       {
           CreateID createID = CreateID.GetInstance();
           //测试是否会生成重复
           Console.WriteLine("单例模式实现,由[0-9a-z]组合生成的唯一值,如下:");
           IList<string> list = new List<string>();
           for (int i = 1; i <= 1000000000; i++)
           {
               string strUniqueNum = createID.CreateUniqueID();
               Console.WriteLine("{0}\t{1}", list.Count, strUniqueNum);
               if (list.Contains(strUniqueNum))
               {
                   Console.WriteLine("{0}值存在重复", strUniqueNum);
                   Console.ReadKey();
               }
               list.Add(strUniqueNum);
               if (i % 200 == 0)
               {
                   Console.WriteLine("没有重复,按Enter键往下看");
                   Console.ReadKey();
               }
           }
           list.Clear();
       }
   }
   /// <summary>
   /// 单例模式实现
   /// 唯一值由[0-9a-z]组合而成,且生成的每个ID不能重复
   /// </summary>
   public class CreateID
   {
       private static CreateID _instance;
       private static readonly object syncRoot = new object();
       private EHashtable hashtable = new EHashtable();
       private string _strXMLURL = string.Empty;
       private CreateID()
       {
           hashtable.Add("0", "0");
           hashtable.Add("1", "1");
           hashtable.Add("2", "2");
           hashtable.Add("3", "3");
           hashtable.Add("4", "4");
           hashtable.Add("5", "5");
           hashtable.Add("6", "6");
           hashtable.Add("7", "7");
           hashtable.Add("8", "8");
           hashtable.Add("9", "9");
           hashtable.Add("10", "a");
           hashtable.Add("11", "b");
           hashtable.Add("12", "c");
           hashtable.Add("13", "d");
           hashtable.Add("14", "e");
           hashtable.Add("15", "f");
           hashtable.Add("16", "g");
           hashtable.Add("17", "h");
           hashtable.Add("18", "i");
           hashtable.Add("19", "j");
           hashtable.Add("20", "k");
           hashtable.Add("21", "l");
           hashtable.Add("22", "m");
           hashtable.Add("23", "n");
           hashtable.Add("24", "o");
           hashtable.Add("25", "p");
           hashtable.Add("26", "q");
           hashtable.Add("27", "r");
           hashtable.Add("28", "s");
           hashtable.Add("29", "t");
           hashtable.Add("30", "u");
           hashtable.Add("31", "v");
           hashtable.Add("32", "w");
           hashtable.Add("33", "x");
           hashtable.Add("34", "y");
           hashtable.Add("35", "z");
           _strXMLURL = System.IO.Path.GetFullPath(@"..\..\") + "XMLs\\record.xml";


       }
       public static CreateID GetInstance()
       {
           if (_instance == null)
           {
               lock (syncRoot)
               {
                   if (_instance == null)
                   {
                       _instance = new CreateID();
                   }
               }
           }
           return _instance;
       }
       /// <summary>
       /// 创建UniqueID
       /// </summary>
       /// <returns>UniqueID</returns>
       public string CreateUniqueID()
       {
           long _uniqueid = GetGuidFromXml();
           return Convert10To36(_uniqueid);
       }
       /// <summary>
       /// 获取UniqueID总记录,即获取得到的这个ID是第几个ID
       /// 更新UniqueID使用的个数,用于下次使用
       /// </summary>
       /// <returns></returns>
       private long GetGuidFromXml()
       {
           long record = 0;
           XmlDocument xmldoc = new XmlDocument();
           xmldoc.Load(_strXMLURL);
           XmlElement rootNode = xmldoc.DocumentElement;
           //此次的个数值
           record = Convert.ToInt64(rootNode["record"].InnerText);
           //此次的个数值+1 == 下次的个数值
           rootNode["record"].InnerText = Convert.ToString(record + 1);
           xmldoc.Save(_strXMLURL);
           return record;
       }
       /// <summary>
       /// 10进制转36进制
       /// </summary>
       /// <param name="intNum10">10进制数</param>
       /// <returns></returns>
       private string Convert10To36(long intNum10)
       {
           string strNum36 = string.Empty;
           long result = intNum10 / 36;
           long remain = intNum10 % 36;
           if (hashtable.ContainsKey(remain.ToString()))
               strNum36 = hashtable[remain.ToString()].ToString() + strNum36;
           intNum10 = result;
           while (intNum10 / 36 != 0)
           {
               result = intNum10 / 36;
               remain = intNum10 % 36;
               if (hashtable.ContainsKey(remain.ToString()))
                   strNum36 = hashtable[remain.ToString()].ToString() + strNum36;
               intNum10 = result;
           }
           if (intNum10 > 0 && intNum10 < 36)
           {
               if (hashtable.ContainsKey(intNum10.ToString()))
                   strNum36 = hashtable[intNum10.ToString()].ToString() + strNum36;
           }
           return strNum36;
       }
   }
   /// <summary>
   /// Summary description for EHashTable
   /// </summary>
   public class EHashtable : Hashtable
   {
       private ArrayList list = new ArrayList();
       public override void Add(object key, object value)
       {
           base.Add(key, value);
           list.Add(key);
       }
       public override void Clear()
       {
           base.Clear();
           list.Clear();
       }
       public override void Remove(object key)
       {
           base.Remove(key);
           list.Remove(key);
       }
       public override ICollection Keys
       {
           get
           {
               return list;
           }
       }
   }
}



XML:


代码 复制 - 运行

<?xml version="1.0" encoding="utf-8"?>
 <root>
   <record id="record">1</record>
</root>





二、在JS中生成GUID,类似.NET中的 Guid.NewGuid(),代码如下:


代码 复制 - 运行

function newGuid() { //方法一:
    var guid = "";
    var n = (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
    for (var i = 1; i <= 8; i++) {
        guid += n;
    }
    return guid;
}
function newGuid() { //方法二:
    var guid = "";
    for (var i = 1; i <= 32; i++) {
        var n = Math.floor(Math.random() * 16.0).toString(16);
        guid += n;
        if ((i == 8) || (i == 12) || (i == 16) || (i == 20))
            guid += "-";
    }
    return guid;
}



三、在SQL存储过程生成GUID,代码如下:


代码 复制 - 运行

-- =============================================
-- Author:      JBen
-- Create date: 2012-06-05
-- Description: 生成唯一标识ID,公共存储过程,可设置在别的存储过程调用此存储过程传不同的前缀
-- =============================================
ALTER PROCEDURE [dbo].[pro_CreateGuid] 
    @Prefix NVARCHAR(10),
    @outputV_guid NVARCHAR(40) OUTPUT
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;
    -- Insert statements for procedure here
    SET @outputV_guid = @Prefix + REPLACE(CAST(NEWID() AS VARCHAR(36)),'-','')
END