.Net短唯一标识符
我在.Net中需要一个唯一的标识符(不能使用GUID,因为这是为了延长这种情况)。 难道人们认为这里使用的algorithmhttp://jopinblog.wordpress.com/2009/02/04/a-shorter-friendlier-guiduuid-in-net/是一个很好的候选人或有任何其他的build议吗?
在这里也是类似于YouTube的GUID
你可以使用Base64:
string base64Guid = Convert.ToBase64String(Guid.NewGuid().ToByteArray());
这会生成一个string,例如E1HKfn68Pkms5zsZsvKONw ==。 由于GUID总是128位,所以可以省略==你知道总是会出现在最后,这会给你一个22个字符的string。 尽pipe这不像YouTube那么简短。
我使用与Dor Cohen类似的方法,但删除了一些特殊字符:
var uid = Regex.Replace(Convert.ToBase64String(Guid.NewGuid().ToByteArray()), "[/+=]", "");
这将只输出字母数字字符。 UID不保证总是相同的长度。 这是一个示例运行:
vmKo0zws8k28fR4V4Hgmw TKbhS0G2V0KqtpHOU8e6Ug rfDi1RdO0aQHTosh9dVvw 3jhCD75fUWjQek8XRmMg CQUg1lXIXkWG8KDFy7z6Ow bvyxW5aj10OmKA5KMhppw pIMK8eq5kyvLK67xtsIDg VX4oljGWpkSQGR2OvGoOQ NOHBjUUHv06yIc7EvotRg iMniAuUG9kiGLwBtBQByfg
对于我的本地应用程序,我使用这种基于时间的方法:
/// <summary> /// Returns all ticks, milliseconds or seconds since 1970. /// /// 1 tick = 100 nanoseconds /// /// Samples: /// /// Return unit value decimal length value hex length /// -------------------------------------------------------------------------- /// ticks 14094017407993061 17 3212786FA068F0 14 /// milliseconds 1409397614940 13 148271D0BC5 11 /// seconds 1409397492 10 5401D2AE 8 /// /// </summary> public static string TickIdGet(bool getSecondsNotTicks, bool getMillisecondsNotTicks, bool getHexValue) { string id = string.Empty; DateTime historicalDate = new DateTime(1970, 1, 1, 0, 0, 0); if (getSecondsNotTicks || getMillisecondsNotTicks) { TimeSpan spanTillNow = DateTime.UtcNow.Subtract(historicalDate); if (getSecondsNotTicks) id = String.Format("{0:0}", spanTillNow.TotalSeconds); else id = String.Format("{0:0}", spanTillNow.TotalMilliseconds); } else { long ticksTillNow = DateTime.UtcNow.Ticks - historicalDate.Ticks; id = ticksTillNow.ToString(); } if (getHexValue) id = long.Parse(id).ToString("X"); return id; }
据我所知, 仅仅剥离一部分GUID并不能保证是唯一的 – 事实上,它远不是唯一的。
杰夫·阿特伍德(Jeff Atwood)在这篇博客中介绍了我所知道的保证全球唯一性的最短的事情。 在链接的post中,他讨论了缩短GUID的多种方法,最后通过Ascii85编码将其降低到20个字节。
但是,如果你绝对需要一个不超过15字节的解决scheme,恐怕你别无select,只能用一些不能保证全局唯一的东西。
var ticks = new DateTime(2016,1,1).Ticks; var ans = DateTime.Now.Ticks - ticks; var uniqueId = ans.ToString("x");
保留一个基线date(在这种情况下是2016年1月1日),从您开始生成这些ID开始。 这将使你的ID更小。
IDENTITY值在数据库中应该是唯一的,但是您应该知道这些限制…例如,如果使用大量logging,批量数据插入基本上不可能,这会降低速度。
您也可以使用date/时间值。 我已经看到了几个数据库,他们使用date/时间作为PK,虽然它不是超级干净 – 它的工作原理。 如果你控制插入,你可以有效地保证这些值在代码中是唯一的。
如果你的应用程序没有几个MILLIION的人,那么在SAME MILLISECOND中使用这个生成短的唯一string,你可以考虑使用下面的函数。
private static readonly Object obj = new Object(); private static readonly Random random = new Random(); private string CreateShortUniqueString() { string strDate = DateTime.Now.ToString("yyyyMMddhhmmssfff"); string randomString ; lock (obj) { randomString = RandomString(3); } return strDate + randomString; // 16 charater } private string RandomString(int length) { const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxy"; var random = new Random(); return new string(Enumerable.Repeat(chars, length) .Select(s => s[random.Next(s.Length)]).ToArray()); }
如果您只是需要在未来99年使用您的应用程序,请将yyyy更改为yy。
更新20160511 :更正随机function
– 添加locking对象
– 从RandomString函数中移出随机variables
参考
在这里我的解决scheme是不安全的并发,每秒不超过1000个GUID和线程安全。
public static class Extensors { private static object _lockGuidObject; public static string GetGuid() { if (_lockGuidObject == null) _lockGuidObject = new object(); lock (_lockGuidObject) { Thread.Sleep(1); var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); var epochLong = Convert.ToInt64((DateTime.UtcNow - epoch).TotalMilliseconds); return epochLong.DecimalToArbitrarySystem(36); } } /// <summary> /// Converts the given decimal number to the numeral system with the /// specified radix (in the range [2, 36]). /// </summary> /// <param name="decimalNumber">The number to convert.</param> /// <param name="radix">The radix of the destination numeral system (in the range [2, 36]).</param> /// <returns></returns> public static string DecimalToArbitrarySystem(this long decimalNumber, int radix) { const int BitsInLong = 64; const string Digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; if (radix < 2 || radix > Digits.Length) throw new ArgumentException("The radix must be >= 2 and <= " + Digits.Length.ToString()); if (decimalNumber == 0) return "0"; int index = BitsInLong - 1; long currentNumber = Math.Abs(decimalNumber); char[] charArray = new char[BitsInLong]; while (currentNumber != 0) { int remainder = (int)(currentNumber % radix); charArray[index--] = Digits[remainder]; currentNumber = currentNumber / radix; } string result = new String(charArray, index + 1, BitsInLong - index - 1); if (decimalNumber < 0) { result = "-" + result; } return result; }
代码没有优化,只是样品!
我知道这是相当远离发布date… 🙂
我有一个发生器只能产生9个hex字符 ,例如:C9D6F7FF3,C9D6FB52C
public class SlimHexIdGenerator : IIdGenerator { private readonly DateTime _baseDate = new DateTime(2016, 1, 1); private readonly IDictionary<long, IList<long>> _cache = new Dictionary<long, IList<long>>(); public string NewId() { var now = DateTime.Now.ToString("HHmmssfff"); var daysDiff = (DateTime.Today - _baseDate).Days; var current = long.Parse(string.Format("{0}{1}", daysDiff, now)); return IdGeneratorHelper.NewId(_cache, current); } } static class IdGeneratorHelper { public static string NewId(IDictionary<long, IList<long>> cache, long current) { if (cache.Any() && cache.Keys.Max() < current) { cache.Clear(); } if (!cache.Any()) { cache.Add(current, new List<long>()); } string secondPart; if (cache[current].Any()) { var maxValue = cache[current].Max(); cache[current].Add(maxValue + 1); secondPart = maxValue.ToString(CultureInfo.InvariantCulture); } else { cache[current].Add(0); secondPart = string.Empty; } var nextValueFormatted = string.Format("{0}{1}", current, secondPart); return UInt64.Parse(nextValueFormatted).ToString("X"); } }
简单的可用包。 我用它来临时请求id生成器。
https://www.nuget.org/packages/shortid
https://github.com/bolorundurowb/shortid
使用System.Random
string id = ShortId.Generate(); // id = KXTR_VzGVUoOY
(从github页面)
如果要通过指定是否需要数字,特殊字符和长度来控制生成的id的types,请调用Generate方法并传递三个参数,第一个布尔值表示是否需要数字,第二个布尔值表示是否需要特殊字符,最后一个数字表示您的长度偏好。
string id = ShortId.Generate(true, false, 12); // id = VvoCDPazES_w
Guid.NewGuid().ToString().Split('-').First()
您可以使用
code = await UserManager.GenerateChangePhoneNumberTokenAsync(input.UserId, input.MobileNumber);
它只有6
漂亮的字符, 143354
当用户简单地virify
var result = await UserManager.VerifyChangePhoneNumberTokenAsync(input.UserId, input.Token, input.MobileNumber);
希望这对你有所帮助
我使用Guid.NewGuid().ToString().Split('-')[0]
,它获取数组中的第一个项,由' – '分隔。 它足以代表一个独特的关键。