7

我正在使用当前时钟滴答作为随机数生成的种子。随机数用于伪 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()
4

2 回答 2

13

您的担心是对的:您应该将Random实例的创建移出方法主体 - 否则您将多次使用相同的值重新播种,从而导致相同的数字序列。

此外,您有点重新发明轮子:该类的默认构造函数Random已经使用当前时钟时间作为默认种子。

问题是您为什么不避免所有这些,而只在数据库端使用自动生成的 Guid?

于 2012-06-05T19:28:02.367 回答
7

引用乔恩·斯基特的话

当您在 Stack Overflow 上的问题标题中看到“随机”一词时,您几乎可以保证这将是与无数类似问题相同的基本问题。本文着眼于为什么随机性会导致如此多的问题,以及如何解决这些问题。

查看他关于随机数生成器的文章

http://cshapindepth.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;
    }
}
于 2012-06-05T19:32:40.473 回答