Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/34.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 18位唯一ID-代码可靠性_C#_Asp.net_Uniqueidentifier - Fatal编程技术网

C# 18位唯一ID-代码可靠性

C# 18位唯一ID-代码可靠性,c#,asp.net,uniqueidentifier,C#,Asp.net,Uniqueidentifier,我想要一个永远唯一的数字,我想出了以下代码, 它生成一个数字,并在其末尾添加一个校验位,我想知道这段代码有多可靠 public void GenerateUniqueNumber(out string ValidUniqueNumber) { string GeneratedUniqueNumber = ""; // Default implementation of UNIX time of the current UTC time TimeS

我想要一个永远唯一的数字,我想出了以下代码, 它生成一个数字,并在其末尾添加一个校验位,我想知道这段代码有多可靠

public void GenerateUniqueNumber(out string ValidUniqueNumber) {
        string GeneratedUniqueNumber = "";

        // Default implementation of UNIX time of the current UTC time
        TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
        string FormatedDateTime = Convert.ToInt64(ts.TotalSeconds).ToString();
        string ssUniqueId = DateTime.UtcNow.ToString("fffffff");
        //Add Padding to UniqueId
        string FormatedUniqueId = ssUniqueId.PadLeft(7, '0'); 

        if (FormatedDateTime.Length == 10 && FormatedUniqueId.Length == 7)
        {
            // Calculate checksum number using Luhn's algorithm.
            int sum = 0;
            bool odd = true;
            string InputData = FormatedDateTime + FormatedUniqueId;
            int CheckSumNumber;

            for (int i = InputData.Length - 1; i >= 0; i--)
            {
                if (odd == true)
                {
                    int tSum = Convert.ToInt32(InputData[i].ToString()) * 2;
                    if (tSum >= 10)
                    {
                        string tData = tSum.ToString();
                        tSum = Convert.ToInt32(tData[0].ToString()) + Convert.ToInt32(tData[1].ToString());
                    }
                    sum += tSum;
                }
                else
                    sum += Convert.ToInt32(InputData[i].ToString());
                odd = !odd;
            }
            //CheckSumNumber = (((sum / 10) + 1) * 10) - sum;
            CheckSumNumber = (((sum + 9) / 10) * 10) - sum;

            // Compute Full length 18 digit UniqueNumber
            GeneratedUniqueNumber = FormatedDateTime + FormatedUniqueId + Convert.ToString(CheckSumNumber);
        }
        else
        {
            // Error
            GeneratedUniqueNumber = Convert.ToString(-1);
        }

        ValidUniqueNumber = GeneratedUniqueNumber;        
    }
编辑:澄清
无法使用GUID,需要通过电话键盘将号码输入IVR系统。

为什么不使用GUID?

如果我正确理解您的实现,它只使用当前日期/时间作为基础。这意味着,如果您同时创建两个ID,它们将不会是唯一的。

正如“Andrew Hare”所说,您可以使用。 关于你的代码,答案是“不”!
因为若客户端计算机的日期时间错误,或者更改结果可能是两个或更多

反正也不是随机的。这里有一个建议

  • 创建您自己的“随机”18位数字
  • 在将其发送给用户之前,请对照数据库中的现有文件进行检查
  • 如果已经在DB中,冲洗并重复

  • 您不能使用GUID,但可以创建类似于GUID的唯一编号格式,该格式基于计算机的MAC地址(空间)和当前时间和日期(时间)。如果所有机器都具有同步时钟,则这保证是唯一的

    有关更多信息,请参见

    ,因为您(在评论中)提到ID存储在数据库中,您可以使用您提到的方法或随机生成ID,并检查数据库中是否存在ID

    如果它已经存在,生成一个新的,否则就完成了

    不过有一件事,我会确保在事务中检查ID的存在和记录到DB的实际保存,否则您将面临另一个请求在检查ID和创建行之间创建该记录的风险


    还只是检查一下,为什么数据库本身生成的自动递增数字不起作用?DB将保证它的唯一性(无论如何,对于该表)

    您不需要说明这些数字的用途。它们是否有某种与之相关的价值?如果用户能够找出方案并猜测有效的票号,这会是一个问题吗

    如果很重要的是这些数字很难猜测,那么这个方案就失败了;输出看起来非常随机的数据会更好。您可以采用单调递增的序列号,并使用分组密码(具有64位块大小)对其进行加密;这将为您提供一个64位的输出或大约20位十进制数字的值,您可以(比如)获取其中的最后18位。(如果可逆性很重要,即给定一个票证号,您希望能够恢复序列号,那么您需要在这里更加小心。)


    你需要一个铁铸的100%保证,没有票号码将永远是相同的吗?如果是这样,您需要将它们保存在数据库中,并在使用时将它们标记出来。如果您这样做,那么使用一个好的随机数生成器并每次检查重复可能是合理的。

    此方法存在一些问题:

    • 你基本上只是在计算1970年1月1日起的毫秒数。您可以从
      ts.TotalSeconds
      四舍五入到0.0000001中获得该值。所有的转换和毫秒计算都是不必要的

    • 10年约为3×10英寸毫秒。您将保留17个有效数字,因此在接下来的10年中,前5个数字将永远不会改变,并且无法用于区分数字。它们是无用的

    • 您是否正在生成1970年到现在之间的毫秒数?如果不是,它们也不能用来区分数字,并且是无用的


    • 这完全取决于返回日期的机器。任何有权使用这台机器的人都可以生成他们想要的任何“唯一”号码。这是问题吗

    • 任何看到其中一个数字的人都可以知道它是何时生成的。这是个问题吗

    • 任何人都可以预测什么时候会产生什么数字。这是个问题吗

    • 1015毫秒大约是30000年。然后,您的算法将重复数字。似乎很长时间了,但你指定了“永远”,30000年不是“永远”。你真的是说“永远”吗


    使用系统时间是一个良好的开端,但如果需要同时生成两个UID,它会导致冲突。使用“fffffff”格式没有任何帮助:Windows时钟分辨率只有15-16毫秒,因此只有一两个“f”做得很好

    另外,您的方法会准确地告诉您ID是何时生成的。根据您的需要,这可能是一个理想的功能,也可能是一个安全风险

    您需要您的ID包含其他信息,而不是时间或时间之外的信息。一些可能的选择是:

    • 随机数
    • 循环计数器
    • 程序名的散列(如果在多个程序中需要这些ID)
    • 机器的MAC地址或其他标识符(如果ID需要在多台计算机上唯一)

    如果要确保唯一性,请将ID存储在数据库中,以便检查重复项。

    Guid只是一个128位的数字。“字母”只是那个数字的十六进制表示形式——这样更容易理解。但是如果他的限制是十进制格式的18位数字,那么GUID就太大了,对吗?@Aaronaught:没必要嘲笑他。如果他什么都知道,他就不需要问问题了。请参阅常见问题解答中的“保持友好”部分:@Matthew:如果您开始从GUID中删除位,它将不再是全局唯一的。“这真是个坏主意!”马修,guid不是随机的。它们是全局唯一的,因为它们包含一个MAC地址(唯一的、全局管理的)和一个精确的、高分辨率的时间戳。因此,它们是时空坐标,如果我们没有MAC地址冲突,它们就不可能发生冲突