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”所说,您可以使用。 关于你的代码,答案是“不”!
因为若客户端计算机的日期时间错误,或者更改结果可能是两个或更多 反正也不是随机的。这里有一个建议
您不能使用GUID,但可以创建类似于GUID的唯一编号格式,该格式基于计算机的MAC地址(空间)和当前时间和日期(时间)。如果所有机器都具有同步时钟,则这保证是唯一的 有关更多信息,请参见,因为您(在评论中)提到ID存储在数据库中,您可以使用您提到的方法或随机生成ID,并检查数据库中是否存在ID 如果它已经存在,生成一个新的,否则就完成了 不过有一件事,我会确保在事务中检查ID的存在和记录到DB的实际保存,否则您将面临另一个请求在检查ID和创建行之间创建该记录的风险
还只是检查一下,为什么数据库本身生成的自动递增数字不起作用?DB将保证它的唯一性(无论如何,对于该表)您不需要说明这些数字的用途。它们是否有某种与之相关的价值?如果用户能够找出方案并猜测有效的票号,这会是一个问题吗 如果很重要的是这些数字很难猜测,那么这个方案就失败了;输出看起来非常随机的数据会更好。您可以采用单调递增的序列号,并使用分组密码(具有64位块大小)对其进行加密;这将为您提供一个64位的输出或大约20位十进制数字的值,您可以(比如)获取其中的最后18位。(如果可逆性很重要,即给定一个票证号,您希望能够恢复序列号,那么您需要在这里更加小心。)
你需要一个铁铸的100%保证,没有票号码将永远是相同的吗?如果是这样,您需要将它们保存在数据库中,并在使用时将它们标记出来。如果您这样做,那么使用一个好的随机数生成器并每次检查重复可能是合理的。此方法存在一些问题:
- 你基本上只是在计算1970年1月1日起的毫秒数。您可以从
四舍五入到0.0000001中获得该值。所有的转换和毫秒计算都是不必要的ts.TotalSeconds
- 10年约为3×10英寸毫秒。您将保留17个有效数字,因此在接下来的10年中,前5个数字将永远不会改变,并且无法用于区分数字。它们是无用的
- 您是否正在生成1970年到现在之间的毫秒数?如果不是,它们也不能用来区分数字,并且是无用的
- 这完全取决于返回日期的机器。任何有权使用这台机器的人都可以生成他们想要的任何“唯一”号码。这是问题吗
- 任何看到其中一个数字的人都可以知道它是何时生成的。这是个问题吗
- 任何人都可以预测什么时候会产生什么数字。这是个问题吗
- 1015毫秒大约是30000年。然后,您的算法将重复数字。似乎很长时间了,但你指定了“永远”,30000年不是“永远”。你真的是说“永远”吗
- 随机数
- 循环计数器
- 程序名的散列(如果在多个程序中需要这些ID)
- 机器的MAC地址或其他标识符(如果ID需要在多台计算机上唯一)
如果要确保唯一性,请将ID存储在数据库中,以便检查重复项。Guid只是一个128位的数字。“字母”只是那个数字的十六进制表示形式——这样更容易理解。但是如果他的限制是十进制格式的18位数字,那么GUID就太大了,对吗?@Aaronaught:没必要嘲笑他。如果他什么都知道,他就不需要问问题了。请参阅常见问题解答中的“保持友好”部分:@Matthew:如果您开始从GUID中删除位,它将不再是全局唯一的。“这真是个坏主意!”马修,guid不是随机的。它们是全局唯一的,因为它们包含一个MAC地址(唯一的、全局管理的)和一个精确的、高分辨率的时间戳。因此,它们是时空坐标,如果我们没有MAC地址冲突,它们就不可能发生冲突