C# .NET短唯一标识符

C# .NET短唯一标识符,c#,.net,uniqueidentifier,C#,.net,Uniqueidentifier,我需要.NET中的唯一标识符(无法使用GUID,因为它对于这种情况来说太长) code = await UserManager.GenerateChangePhoneNumberTokenAsync(input.UserId, input.MobileNumber); 人们认为所使用的算法是一个很好的候选算法吗?或者你还有其他建议吗?这一个很好- code = await UserManager.GenerateChangePhoneNumberTokenAsync(input.UserId,

我需要.NET中的唯一标识符(无法使用GUID,因为它对于这种情况来说太长)

code = await UserManager.GenerateChangePhoneNumberTokenAsync(input.UserId, input.MobileNumber);
人们认为所使用的算法是一个很好的候选算法吗?或者你还有其他建议吗?

这一个很好-

code = await UserManager.GenerateChangePhoneNumberTokenAsync(input.UserId, input.MobileNumber);
还有这里

code = await UserManager.GenerateChangePhoneNumberTokenAsync(input.UserId, input.MobileNumber);
您可以使用Base64:

string base64Guid = Convert.ToBase64String(Guid.NewGuid().ToByteArray());
code = await UserManager.GenerateChangePhoneNumberTokenAsync(input.UserId, input.MobileNumber);
这将生成一个类似于e1hkfn68pkms5zsvkonw==的字符串。因为GUID是 始终为128位,您可以省略您知道将始终为的== 在结尾出现,这将给你一个22个字符的字符串。这 但它没有YouTube那么短

code = await UserManager.GenerateChangePhoneNumberTokenAsync(input.UserId, input.MobileNumber);

标识值在数据库中应该是唯一的,但您应该知道其局限性。。。例如,它使批量数据插入基本上不可能,如果您处理大量记录,这将使您的速度减慢

code = await UserManager.GenerateChangePhoneNumberTokenAsync(input.UserId, input.MobileNumber);

您还可以使用日期/时间值。我见过几个数据库,它们使用日期/时间作为主键,虽然它不是超级干净的,但可以工作。如果控制插入,可以有效地保证代码中的值是唯一的。

对于我的本地应用程序,我使用基于时间的方法:

/// <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;
}
code = await UserManager.GenerateChangePhoneNumberTokenAsync(input.UserId, input.MobileNumber);
//
///返回自1970年以来的所有滴答声、毫秒或秒。
/// 
///1滴答=100纳秒
/// 
///样本:
/// 
///返回单位值十进制长度值十六进制长度
/// --------------------------------------------------------------------------
///刻度14094017407993061 17 3212786FA068F0 14
///毫秒1409397614940 13 148271D0BC5 11
///秒1409397492 10 5401D2AE 8
///
/// 
公共静态字符串TickIdGet(bool getSecondsNotTicks、bool getmillisondsnotticks、bool getHexValue)
{
string id=string.Empty;
DateTime historicalDate=新的日期时间(1970,1,1,0,0);
if(GetSecondSnoticks | | GetMillistSecondSnoticks)
{
TimeSpan spanTillNow=DateTime.UtcNow.Subtract(历史日期);
如果(获取第二个snotticks)
id=String.Format(“{0:0}”,spanTillNow.TotalSeconds);
其他的
id=String.Format(“{0:0}”,spanTillNow.total毫秒);
}
其他的
{
long ticksTillNow=DateTime.UtcNow.Ticks-historicalDate.Ticks;
id=ticksTillNow.ToString();
}
if(getHexValue)
id=long.Parse(id).ToString(“X”);
返回id;
}
据我所知,-事实上,它远非独一无二

code = await UserManager.GenerateChangePhoneNumberTokenAsync(input.UserId, input.MobileNumber);
我所知道的保证全球唯一性的最短的事情是。在这篇链接文章中,他讨论了缩短GUID的多种方法,最后通过via将其缩减为20个字节

code = await UserManager.GenerateChangePhoneNumberTokenAsync(input.UserId, input.MobileNumber);

但是,如果您确实需要一个长度不超过15字节的解决方案,恐怕您别无选择,只能使用不保证全局唯一的解决方案。

在这里,我的解决方案对于并发不安全,每秒不超过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;
    }
code = await UserManager.GenerateChangePhoneNumberTokenAsync(input.UserId, input.MobileNumber);
公共静态类扩展名
{
私有静态对象_lockGuidObject;
公共静态字符串GetGuid()
{
if(_lockGuidObject==null)
_lockGuidObject=新对象();
锁(_lockGuidObject)
{
睡眠(1);
var epoch=新的日期时间(1970,1,1,0,0,0,DateTimeKind.Utc);
var epochLong=Convert.ToInt64((DateTime.UtcNow-epoch).total毫秒);
返回epochLong.DecimalToArbitrarySystem(36);
}
}
/// 
///将给定的十进制数转换为具有
///指定的基数(范围为[2,36])。
/// 
///要转换的数字。
///目标数字系统的基数(在[2,36]范围内)。
/// 
公共静态字符串DecimalTorBitrarySystem(此长小数,整数基数)
{
常数int位长=64;
常量字符串数字=“0123456789abcdefghijklmnopqrstuvxyz”;
if(基数<2 | |基数>位数.长度)

抛出新ArgumentException(“基数必须>=2且如果你的应用程序没有几百万人,在同一毫秒内使用生成短的唯一字符串,你可以考虑使用下面的函数

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());
}
code = await UserManager.GenerateChangePhoneNumberTokenAsync(input.UserId, input.MobileNumber);
如果您只需要在下一个99年使用您的应用程序,请将yyyy更改为yy。
更新20160511:更正随机函数
-添加锁对象
将随机变量移出RandomString函数

我知道离发布日期很远……:)

code = await UserManager.GenerateChangePhoneNumberTokenAsync(input.UserId, input.MobileNumber);
我有一个只生成9个六进制字符的生成器,例如: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");
    }
}
code = await UserManager.GenerateChangePhoneNumberTokenAsync(input.UserId, input.MobileNumber);
公共类SlimHexIdGenerator:IIdGenerator
{
私有只读日期时间_baseDate=新日期时间(2016,1,1);
私有只读IDictionary_cache=new Dictionary();
公共字符串NewId()
{
var now=DateTime.now.ToString(“HHmmssfff”);
var daysDiff=(DateTime.Today-_baseDate).Days;
var current=long.Parse(string.Format(“{0}{1}”),daysDiff,now));
返回IdGeneratorHelper.NewId(_缓存,当前);
}
}
静态类IdGeneratorHelper
{
公共静态字符串NewId(IDictionary缓存,长当前)
{
if(cache.Any()&&cache.Keys.Max()
您可以使用

code = await UserManager.GenerateChangePhoneNumberTokenAsync(input.UserId, input.MobileNumber);
它的
6
字符很好,
599527
143354

code = await UserManager.GenerateChangePhoneNumberTokenAsync(input.UserId, input.MobileNumber);
当我们
    public static string ToTinyUuid(this Guid guid)
    {
        return Convert.ToBase64String(guid.ToByteArray())[0..^2]  // remove trailing == padding 
            .Replace('+', '-')                          // escape (for filepath)
            .Replace('/', '_');                         // escape (for filepath)
    }
Guid.NewGuid().ToTinyUuid()
private static readonly object _getUniqueIdLock = new object();
public static string GetUniqueId()
{       
    lock(_getUniqueIdLock)
    {
        System.Threading.Thread.Sleep(1);
        return DateTime.UtcNow.Ticks.ToString("X");
    }
}
// Our url safe, base 64 alphabet:
const string alphabet = "-_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

// Sanitized Guid string. Preserve the last two hex chars
var guidStr = "929F7C4D4B2644E1A122A379C02D6345";
var lastTwo = guidStr.Substring(30, 2);

string shortGuid = "";

// Iterate over the ten groups of 3 hex chars: 929 F7C 4D4 B26 44E 1A1 22A 379 C02 D63
for (var i = 0; i < 10; i++)
{
    var hex = guidStr.Substring(i*3, 3);              // Get the next 3 hex chars
    var x = Convert.ToInt32(hex, 16);                 // Convert to int
    shortGuid += $"{alphabet[x/64]}{alphabet[x%64]}"; // Lookup the two-digit base64 value
}
shortGuid += lastTwo; // Don't forget the last two

Console.WriteLine(shortGuid);
yDXWhiGAfc4v6EbTK0Px45
Guid.NewGuid().ToString("n")
5db4cee3bfd8436395d37fca2d48d5b3
82fac271c76148a3a0667c00a5da990d