1

我有一个描述地址的结构,它看起来像:

class Address
{
    public string AddressLine1 { get; set; }
    public string AddressLine2 { get; set; }
    public string City { get; set; }
    public string Zip { get; set; }
    public string Country { get; set; }
} 

我正在寻找一种方法来为这个结构创建一个唯一标识符(我假设它也应该属于 类型string),这取决于所有结构属性(例如,更改AddressLine1也会导致结构标识符的更改)。

我知道,我可以将所有属性连接在一起,但这会给出太长的标识符。我正在寻找比这短得多的东西。

我还假设不同地址的数量不应该超过100M。

关于如何生成此标识符的任何想法?

提前致谢。

史前史:

数据库中有几个不同的表,其中包含一些信息+地址数据。数据以类似于上述格式的格式存储。

不幸的是,现在将地址数据移动到单独的表中非常昂贵,但我希望将来会这样做。

我需要将一些附加属性与地址数据相关联,并为此创建一个单独的表。这就是为什么我需要唯一标识地址数据。

4

2 回答 2

3

将所有字段序列化为一个大的二进制值。例如,使用具有适当域分隔的连接。

然后使用足够长度的加密散列对该值进行散列。我更喜欢 256 位,但 128 位可能没问题。具有良好哈希的冲突极为罕见,对于像 SHA-256 这样的 256 位哈希,它们几乎是不可能的。

于 2013-04-07T12:18:38.707 回答
0

这是一个使用序列化、sha256 散列和 base64 编码的完整示例(基于 CodesInChaos 答案):

using System;
using System.IO;
using System.Security.Cryptography;
using System.Runtime.Serialization.Formatters.Binary;

namespace Uniq
{
    [Serializable]
    class Address
    {
        public string AddressLine1 { get; set; }
        public string AddressLine2 { get; set; }
        public string City { get; set; }
        public string Zip { get; set; }
        public string Country { get; set; }
    } 
    class MainClass
    {
        public static void Main (string[] args)
        {
            Address address1 = new Address(){AddressLine1 = "a1"};
            Address address2 = new Address(){AddressLine1 = "a1"};
            Address address3 = new Address(){AddressLine1 = "a2"};
            string unique1 = GetUniqueIdentifier(address1);
            string unique2 = GetUniqueIdentifier(address2);
            string unique3 = GetUniqueIdentifier(address3);
            Console.WriteLine(unique1);
            Console.WriteLine(unique2);
            Console.WriteLine(unique3);
        }
        public static string GetUniqueIdentifier(object obj){
            if (obj == null) return "0";
            SHA256 mySHA256 = SHA256Managed.Create ();
            BinaryFormatter formatter = new BinaryFormatter ();
            MemoryStream stream = new MemoryStream();
            formatter.Serialize(stream, obj);
            byte[] hash = mySHA256.ComputeHash(stream.GetArray());
            string uniqId = Convert.ToBase64String(hash);
            return uniqId;
        }
    }
}

编辑:这是一个不使用BinaryFormatter. 您可以将空表示和字段分隔符替换为适合您需要的任何内容。

public static string GetUniqueIdentifier(object obj){
    if (obj == null) return "0";
    SHA256 mySHA256 = SHA256Managed.Create ();
    StringBuilder stringRep = new StringBuilder();
    obj.GetType().GetProperties()
                .ToList().ForEach(p=>stringRep.Append(
            p.GetValue(obj, null) ?? '¨'
            ).Append('^'));
    Console.WriteLine(stringRep);
    Console.WriteLine(stringRep.Length);
    byte[] hash = mySHA256.ComputeHash(Encoding.Unicode.GetBytes(stringRep.ToString()));
    string uniqId = Convert.ToBase64String(hash);
    return uniqId;
}
于 2013-04-07T13:01:31.523 回答