我正在使用当前时钟滴答作为随机数生成的种子。随机数用于伪GUID,我的数据库中的检查将确保它在返回之前不存在。平均而言,这个方法将在过程的生命周期中连续调用大约10k次。
我担心的是,可能会背靠背生成相同的数字,导致对我的数据库进行多次不必要的递归调用,检查是否存在相同的ID。如果可能的话,我想避免这种情况。测试这种情况的最佳方法是什么?
如果重要,应用程序是.NET 4,数据库是SQL Server 2008。
private static string GenerateUniqueDelId()
{
// Generate a random integer using the current number of clock ticks as seed.
// Then prefix number with "DEL" and date, finally padding random integer with leading zeros for a fixed 25-character total length.
int seed = (int)DateTime.Now.Ticks;
Random number = new Random(seed);
string id = string.Format("DEL{0}{1}", DateTime.Today.ToString("yyyyMMdd"), number.Next().ToString("D14"));
// Lookup record with generated ID in Sesame. If one exists, call method recursively.
string query = "SELECT * FROM Lead WHERE Esm_Id = @Esm_Id";
SqlParameter[] parameters = { new SqlParameter("@Esm_Id", id) };
if (DataManager.GetRow(query, parameters, DelConnection.Sesame) != null) return GenerateUniqueDelId();
// Otherwise, return ID.
return id;
} //// End GenerateUniqueDelId()
答案 0 :(得分:11)
您的关注点是正确的:您应该将Random
实例的创建移出方法体 - 否则您将使用相同的值重新播种多次,从而产生相同的数字序列。< / p>
此外,您还在重新发明轮子:Random
类的默认构造函数已将当前时钟时间用作默认种子。
问题是为什么不避免所有这些,只是在数据库端使用自动生成的Guid?
答案 1 :(得分:7)
引用Jon Skeet
当您在Stack Overflow上的问题标题中看到“随机”一词时,几乎可以保证它与无数类似问题的基本问题相同。本文将介绍为什么随机性会导致很多问题,以及如何解决这些问题。
查看他关于随机数生成器的文章
http://csharpindepth.com/Articles/Chapter12/Random.aspx
基本上他的解决方案看起来像:
using System;
using System.Threading;
public static class RandomProvider
{
private static int seed = Environment.TickCount;
private static ThreadLocal<Random> randomWrapper = new ThreadLocal<Random>(() =>
new Random(Interlocked.Increment(ref seed))
);
public static Random GetThreadRandom()
{
return randomWrapper.Value;
}
}