.NET короткий уникальный идентификатор - PullRequest
64 голосов
/ 14 февраля 2012

Мне нужен уникальный идентификатор в .NET (невозможно использовать GUID, поскольку он слишком длинный для этого случая).

Считают ли люди, что используемый здесь является хорошим кандидатом илиу вас есть другие предложения?

Ответы [ 16 ]

68 голосов
/ 14 февраля 2012

Это хороший - http://www.singular.co.nz/blog/archive/2007/12/20/shortguid-a-shorter-and-url-friendly-guid-in-c-sharp.aspx

а также здесь GUID, похожий на YouTube

Вы можете использовать Base64:

string base64Guid = Convert.ToBase64String(Guid.NewGuid().ToByteArray());

Это генерирует строку вроде E1HKfn68Pkms5zsZsvKONw ==. Поскольку GUID всегда 128 бит, вы можете опустить ==, что вы знаете, всегда будет присутствует в конце, и это даст вам строку из 22 символов. это не такой короткий, как YouTube.

26 голосов
/ 03 февраля 2017

Я использую тот же подход, что и Дор Коэн, но удаляю некоторые специальные символы:

var uid = Regex.Replace(Convert.ToBase64String(Guid.NewGuid().ToByteArray()), "[/+=]", "");     

Это выведет только буквенно-цифровые символы. Гарантируется, что идентификаторы UID всегда имеют одинаковую длину. Вот примерный прогон:

vmKo0zws8k28fR4V4Hgmw 
TKbhS0G2V0KqtpHOU8e6Ug 
rfDi1RdO0aQHTosh9dVvw
3jhCD75fUWjQek8XRmMg 
CQUg1lXIXkWG8KDFy7z6Ow 
bvyxW5aj10OmKA5KMhppw
pIMK8eq5kyvLK67xtsIDg
VX4oljGWpkSQGR2OvGoOQ 
NOHBjUUHv06yIc7EvotRg
iMniAuUG9kiGLwBtBQByfg
13 голосов
/ 18 января 2017
var ticks = new DateTime(2016,1,1).Ticks;
var ans = DateTime.Now.Ticks - ticks;
var uniqueId = ans.ToString("x");

Сохраните базовую дату (которая в данном случае 1 января 2016 г.) с момента, когда вы начнете генерировать эти идентификаторы. Это уменьшит ваши идентификаторы.

Генерируемый номер: 3af3c14996e54

12 голосов
/ 31 августа 2017

Простой в использовании пакет. Я использую его для генератора идентификаторов временных запросов.

https://www.nuget.org/packages/shortid

https://github.com/bolorundurowb/shortid

Использует System.Random

string id = ShortId.Generate();
// id = KXTR_VzGVUoOY

(со страницы github)

Если вы хотите контролировать тип сгенерированного идентификатора, указав, хотите ли вы числа, специальные символы и длину, вызовите метод Generate и передайте три параметра, первый - логическое значение, указывающее, хотите ли вы числа, второй - логическое выражение. хотите ли вы специальные символы, последний номер, указывающий ваши предпочтения длины.

string id = ShortId.Generate(true, false, 12);
// id = VvoCDPazES_w
8 голосов
/ 09 ноября 2014

Насколько я знаю, простое удаление части GUID не гарантированно уникально - фактически, это далеко не уникально.

Самое короткое, чтоЯ знаю, что это гарантирует глобальную уникальность в этом блоге Джеффа Этвуда .В связанном посте он обсуждает несколько способов сократить GUID и в конце концов уменьшает его до 20 байтов с помощью кодировки Ascii85 .

Однако, если вам абсолютно необходимо решение, которого нетболее 15 байт, я боюсь, у вас нет другого выбора, кроме как использовать что-то, что не гарантированно является глобально уникальным.

6 голосов
/ 30 августа 2014

Для моего локального приложения я использую подход, основанный на времени:

/// <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;
}
5 голосов
/ 14 февраля 2012

Значения IDENTITY должны быть уникальными в базе данных, но вы должны знать об ограничениях ... например, это делает невозможным массовое вставление данных, что замедлит вас, если вы работаете с очень большим количеством записей .

Вы также можете использовать значение даты / времени. Я видел несколько баз данных, где они используют дату / время, чтобы быть PK, и хотя это не супер чисто - это работает. Если вы контролируете вставки, вы можете эффективно гарантировать, что значения будут уникальными в коде.

3 голосов
/ 26 октября 2015

Если в вашем приложении нет нескольких МИЛЛИОНОВ человек, использующих эту короткую уникальную строку в ОДНОМ И МИЛЛИСЕКОНДЕ, вы можете подумать об использовании функции ниже.

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());
}

измените yyyy на yy, если вам просто нужноИспользуйте ваше приложение в ближайшие 99 лет. Обновление 20160511 : функция исправления случайных- Добавить объект блокировки- Переместить случайную величину из функции RandomString Ref

2 голосов
/ 14 июля 2015

здесь мое решение, небезопасно для параллелизма, не более 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;
    }

код не оптимизирован, просто пример!.

1 голос
/ 13 февраля 2018

На основании ответа @ dorcohen и комментария @ pootzko. Вы можете использовать это. Это безопасно по проводу.

var errorId = System.Web.HttpServerUtility.UrlTokenEncode(Guid.NewGuid().ToByteArray());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...