【问题标题】:DataRow GetHashCode() method value won't change after editing rowDataRow GetHashCode() 方法值在编辑行后不会改变
【发布时间】:2014-06-30 18:31:08
【问题描述】:

我有一个数据表,我想在对数据表的行进行编辑之前和之后比较每一行的哈希码 这就是我获取 HashCode 的方式,将其与键一起存储在字典中,然后返回

        Dictionary<string, int> mydict1= new Dictionary<string, int>();

        foreach (DataRow row in DataTable.Rows)
        {
            mydict.Add(row["Name"].ToString(), row.GetHashCode());
        }

        return mydict1;

编辑数据表行中的值后,我再次调用相同的函数并获取行的所有哈希码值并将其存储在 mydict2 中。 当我比较 mydict1 和 mydict2 时,它们完全相同,即使我已经对行进行了编辑。如何捕获编辑?或者我怎样才能得到一行中值的哈希码?也许我没有正确获取哈希码,请帮助。

【问题讨论】:

  • 您不应该使用Object.GetHashCode() 提供的哈希以这种方式比较对象。来自 MSDN “不要测试哈希码的相等性以确定两个对象是否相等。(不相等的对象可以具有相同的哈希码。)要测试相等,请调用 ReferenceEquals 或 Equals 方法。”
  • “我想在对数据表的行进行编辑之前和之后比较每一行的哈希码” 为什么要这样做?这听起来像XY Problem 告诉我们您认为比较哈希码是解决方案的问题,我们会告诉您解决该问题的正确方法。
  • 如果您想确定哪些行已被修改,您可以改用DataRow.RowState
  • 我想知道行是否被修改,以及那些已经被修改的行,保存到数据库。你知道我怎样才能得到行的校验和吗? Datarow.Rowstate 对我没有帮助。
  • "Datarow.Rowstate 对我的情况没有帮助" 为什么不呢?

标签: c# .net datatable hashcode


【解决方案1】:

我假设您没有使用自定义 DataRow 类,并且您期望 GetHashcode 根据 DataRow 的内容返回某种“校验和”值。

GetHashCode 不是这样做的,不应该这样做。哈希码用于将项目存储在Dictionary 或其他基于哈希的集合中。

来自MSDN

哈希码是一个数值,用于在基于哈希的集合中插入和标识对象,例如Dictionary&lt;TKey, TValue&gt; 类、Hashtable 类或派生自DictionaryBase 类的类型。

GetHashCode 的默认行为为对象的相等 instances 返回相等的哈希码,而不管该对象内的任何基础值,这就是为什么您在之后得到相同值的原因变化。

请阅读上面链接的其余文档,了解哈希码的其他适当(和不适当)用途。

如果您想可靠地查看某行是否已被修改,则必须保留先前值的副本并逐列比较它们 .对于具有不同列值的行,任何散列算法可能产生相同的校验和。

可以使用DataRowComparer.GetHashCode(),但请注意,它不能 100% 保证指示行是否已更改。

【讨论】:

  • 哦,我明白了。这正是我想要得到的——数据行的校验和。我正在考虑将数据行的值连接到单个字符串中,然后将其转换为二进制或类似的东西,以获取校验和,您有什么想法如何以更好的方式获取原始校验和吗?
  • 您可以使用Sha1.ComputeHash() 之类的东西,但这需要您将每个列值转换为某种字节数组。
【解决方案2】:

我使用了一种方法来验证来自 CSV 的传入数据行是否已更改。最初我使用 GetHAshCode() 只是为了发现它不会像我想象的那样工作。

这就是我所做的......

我创建了一个SHA1哈希方法如下:

    static string Hash(string input)
    {
        using (SHA1Managed sha1 = new SHA1Managed())
        {
            var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(input));
            var sb = new StringBuilder(hash.Length * 2);

            foreach (byte b in hash)
            {
                // can be "x2" if you want lowercase
                sb.Append(b.ToString("X2"));
            }

            return sb.ToString();
        }
    }

要将数据行转换为字符串值,我执行了以下操作:

    string _szImportRecordHash = Hash(String.Join(",", drRow.ItemArray) );

上面的代码有一个 String.Join,它接受 itemArray 并返回一个逗号分隔的字符串。

然后我将此值存储在数据库中并比较单个哈希以验证行已更改。如果不匹配,则我将更改处理到各个项目的数据库中。

这对我来说效果很好。

【讨论】:

    猜你喜欢
    • 2014-07-01
    • 2021-07-24
    • 1970-01-01
    • 2014-02-27
    • 2015-04-07
    • 1970-01-01
    • 1970-01-01
    • 2011-10-16
    • 2023-03-26
    相关资源
    最近更新 更多