Мне нужен уникальный идентификатор в .NET (не могу использовать GUID, так как он слишком длинный для этого случая).
Считают ли люди, что используемый здесь алгоритм является хорошим кандидатом, или у вас есть другие предложения?
Мне нужен уникальный идентификатор в .NET (не могу использовать GUID, так как он слишком длинный для этого случая).
Считают ли люди, что используемый здесь алгоритм является хорошим кандидатом, или у вас есть другие предложения?
Этот хороший - http://www.singular.co.nz/blog/archive/2007/12/20/shortguid-a-shorter-and-url-friendly-guid-in-c-sharp.aspx
а также здесь YouTube-подобный GUID
Вы можете использовать Base64:
string base64Guid = Convert.ToBase64String(Guid.NewGuid().ToByteArray());
Это генерирует строку, такую как E1HKfn68Pkms5zsZsvKONw ==. Поскольку идентификатор GUID всегда 128 бит, вы можете опустить ==, который, как вы знаете, всегда будет присутствует в конце, и это даст вам строку из 22 символов. Эта не так короток, как YouTube.
Я использую такой же подход, как Дор Коэн, но удаляю некоторые специальные символы:
var uid = Regex.Replace(Convert.ToBase64String(Guid.NewGuid().ToByteArray()), "[/+=]", "");
Это выведет только буквенно-цифровые символы. Гарантируется, что идентификаторы UID всегда имеют одинаковую длину. Вот примерный прогон:
vmKo0zws8k28fR4V4Hgmw
TKbhS0G2V0KqtpHOU8e6Ug
rfDi1RdO0aQHTosh9dVvw
3jhCD75fUWjQek8XRmMg
CQUg1lXIXkWG8KDFy7z6Ow
bvyxW5aj10OmKA5KMhppw
pIMK8eq5kyvLK67xtsIDg
VX4oljGWpkSQGR2OvGoOQ
NOHBjUUHv06yIc7EvotRg
iMniAuUG9kiGLwBtBQByfg
Простой в использовании пакет. Я использую его для генератора временных запросов.
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
var ticks = new DateTime(2016,1,1).Ticks;
var ans = DateTime.Now.Ticks - ticks;
var uniqueId = ans.ToString("x");
Сохраните базовую дату (которая в данном случае - 1 января 2016 года) с момента, когда вы начнете генерировать эти идентификаторы. Это сделает ваши идентификаторы меньше.
Сгенерированный номер: 3af3c14996e54
Насколько я знаю, просто отрисовка части GUID не гарантируется быть уникальной - на самом деле это далеко не будучи уникальным.
Самая короткая вещь, которую я знаю, которая гарантирует глобальную уникальность, представлена в в этом блоге Джеффом Этвудом. В связанном сообщении он обсуждает несколько способов сократить GUID и в итоге получает до 20 байтов через Ascii85 encoding.
Однако, если вам абсолютно необходимо решение, которое не превышает 15 байт, я боюсь, что у вас нет другого выбора, кроме как использовать что-то, что не гарантируется в глобальном масштабе.
Для моего локального приложения я использую этот подход, основанный на времени:
/// <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;
}
Значения IDENTITY должны быть уникальными в базе данных, но вы должны знать об ограничениях... например, это делает невозможным вложение больших данных, что замедлит вас, если вы работаете с очень большим количеством записей.
Вы также можете использовать значение даты/времени. Я видел несколько баз данных, где они используют дату/время, чтобы быть ПК, и хотя он не супер чистый - он работает. Если вы управляете вставками, вы можете эффективно гарантировать, что значения будут уникальными в коде.
Если в вашем приложении нет нескольких МИЛЛИОНОВ людей, использующих эту короткую уникальную строку в ОДНОМ ТОЛЬКО МИЛЛИСЕКОНД, вы можете подумать об использовании функции ниже.
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
ссылка
здесь мое решение, небезопасно для concurrency, не более 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;
}
код не оптимизирован, просто образец!.
Я знаю, что это довольно далеко от опубликованной даты...:)
У меня есть генератор, который производит только 9 символов Hexa, например: 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");
}
}
Я использую следующее, чтобы создать уникальный гид (35 символов).
// Example: 7b08e3d-186b-46f0-99c8-e8252033715d
var strUniqueGuid = Guid.NewGuid().ToString();
Если вам нравится уникальный гид с 16 символами, используйте приведенный ниже код
// Example: 7b08e3d-186b-46f
var strUniqueGuid = Guid.NewGuid().ToString();
strUniqueGuid=strUniqueGuid.Substring(0, 16);
Один лайнер от @adeel41 ответ:
var uniqueId = (DateTime.Now.Ticks - new DateTime(2016, 1, 1).Ticks).ToString("x");
Результаты в т. Е.:
3bcc640029e88
Основано на ответе @dorcohen и комментарии @pootzko. Вы можете использовать это. Это безопасно по проводу.
var errorId = System.Web.HttpServerUtility.UrlTokenEncode(Guid.NewGuid().ToByteArray());
Если вам не нужно вводить строку, вы можете использовать следующее:
static class GuidConverter
{
public static string GuidToString(Guid g)
{
var bytes = g.ToByteArray();
var sb = new StringBuilder();
for (var j = 0; j < bytes.Length; j++)
{
var c = BitConverter.ToChar(bytes, j);
sb.Append(c);
j++;
}
return sb.ToString();
}
public static Guid StringToGuid(string s)
=> new Guid(s.SelectMany(BitConverter.GetBytes).ToArray());
}
Это преобразует Guid в 8-символьную строку следующим образом:
{b77a49a5-182b-42fa-83a9-824ebd6ab58d} → "䦥 띺 ᠫ 䋺 ꦃ 亂 檽 趵"
{c5f8f7f5-8a7c-4511-b667-8ad36b446617} → " 엸 詼 䔑 架 펊 䑫 ᝦ"
вы можете использовать
code = await UserManager.GenerateChangePhoneNumberTokenAsync(input.UserId, input.MobileNumber);
его 6
только приятные символы, 599527
, 143354
и когда пользователь virify просто
var result = await UserManager.VerifyChangePhoneNumberTokenAsync(input.UserId, input.Token, input.MobileNumber);
надеюсь, что это поможет вам
Я использую Guid.NewGuid().ToString().Split('-')[0]
, он получает первый элемент из массива, разделенный символом '-'. Его достаточно, чтобы представить уникальный ключ.
Guid.NewGuid().ToString().Split('-').First()