【问题标题】:Creating Guid using a hash of a string使用字符串的哈希创建 Guid
【发布时间】:2020-06-18 23:25:42
【问题描述】:

我正在玩弄在 noSQL 数据库中使用 Guid 作为 PrimaryKey 的想法,这是三个不同属性的组合(这可能是个坏主意)。这三个属性是;两个整数和一个 DateTime - 它们在组合时是唯一的。我使用 Guid 的原因是因为相同结构的预先存在的数据使用 Guid 而不是这些属性来查找数据。

如果我将它们转换为字符串并连接它们。然后我转换为 byte[] 并创建一个 Guid。发生碰撞的可能性有多大?我认为散列将是这里的问题?如果我使用弱的 16 字节散列算法,例如 MD5,如果属性不同,两个 guid 匹配(冲突)的机会是多少?例如整数和日期时间?如果我使用像 SHA256 这样的散列算法并且只使用前 16 个字节而不是 MD5,会发生什么情况?碰撞的几率还是一样吗?

否则,如果需要,我还有其他选项,例如二次查找,但这会使写入、读取和成本加倍。

例子:

        public static Guid GenerateId(int locationId, int orderNumber, DateTime orderDate)
    {
        var combined = $"{locationId}{orderNumber}{orderDate.ToString("d", CultureInfo.InvariantCulture)}";
        using (MD5 md5 = MD5.Create())
        {
            byte[] hash = md5.ComputeHash(Encoding.Default.GetBytes(combined));
            return new Guid(hash);
        }
    }

【问题讨论】:

  • 为什么要散列?如果您确定这三个参数的组合始终是唯一的,则使用该数据创建一个 GUID,DateTime 的长度为 8 个字节,整数为 4,因此您有 16 个字节,即 GUID 的确切长度...

标签: c# guid hashcode


【解决方案1】:

为什么要散列?如果您完全确定这三个参数组合始终是唯一的,那么您拥有创建唯一 GUID 所需的所有数据。 DateTime 是 8 个字节长,int 是 4 个字节长,所以你的数据是 16 个字节长,这就是 GUID 的确切大小。您可以使用 BitConverter 获取这些值的字节,并使用 GUID 的构造函数,该构造函数采用 16 字节数组:

DateTime firstValue = DateTime.Now; //Or whatever it is
int secondValue = 33; //whatever
int thirdValue = 44;  //whatever

List<byte> tempBuffer = new List<byte>();

tempBuffer.AddRange(BitConverter.GetBytes(firstValue.ToBinary())); //Needs to convert to long first with ToBinary
tempBuffer.AddRange(BitConverter.GetBytes(secondValue));
tempBuffer.AddRange(BitConverter.GetBytes(thirdValue));

Guid id = new Guid(tempBuffer.ToArray());

【讨论】:

  • 太棒了,谢谢!有趣的是你如何进入兔子洞,简单的加法会给我答案!
猜你喜欢
  • 2011-01-01
  • 2020-06-05
  • 2010-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-11
  • 1970-01-01
相关资源
最近更新 更多