1

我在我的应用程序中使用实体框架。

我用实体的部分类实现了IEquatable<T>接口:

Partial Class Address : Implements IEquatable(Of Address) 'Other part generated
  Public Overloads Function Equals(ByVal other As Address) As Boolean _
      Implements System.IEquatable(Of Address).Equals
    If ReferenceEquals(Me, other) Then Return True
    Return AddressId = other.AddressId
  End Function

  Public Overrides Function Equals(ByVal obj As Object) As Boolean
    If obj Is Nothing Then Return MyBase.Equals(obj)
    If TypeOf obj Is Address Then 
      Return Equals(DirectCast(obj, Address)) 
  Else
    Return False
  End Function

  Public Overrides Function GetHashCode() As Integer
    Return AddressId.GetHashCode
  End Function
End Class

现在在我的代码中,我以这种方式使用它:

Sub Main()
  Using e As New CompleteKitchenEntities
    Dim job = e.Job.FirstOrDefault
    Dim address As New Address()

    job.Addresses.Add(address)
    Dim contains1 = job.Addresses.Contains(address) 'True
    e.SaveChanges()
    Dim contains2 = job.Addresses.Contains(address) 'False

    'The problem is that I can't remove it:
    Dim removed = job.Addresses.Remoeve(address) 'False

  End Using
End Sub

注意(我在调试器可视化器中检查)EntityCollection 类将其实体存储在 HashSet 中,因此它与 GetHashCode 函数有关,我希望它依赖于 ID,因此实体通过它们的 ID 进行比较。

问题是当我点击保存时,ID 从 0 变为它的 db 值。所以问题是我怎样才能有一个平等的对象,被正确地散列。

请帮助我找出 GetHashCode 函数中的问题(按 ID)以及我可以更改哪些内容以使其正常工作。

非常感谢。

4

2 回答 2

1

您已使用可变字段 ( AddressId) 作为散列的一部分 - 不幸的是,这注定要失败。我的意思是:当你添加它时,它AddressId是 0?-1?究竟是什么并不重要,但它不是最终的 id - 它与这个密钥/哈希一起存储。当您保存它时,实际的id(IDENTITY数据库中的列)会更新到对象中。

很简单,如果它是字典的一部分时可以更改,则无法可靠地针对该值进行散列。一种可能的解决方法是考虑工作单元,即插入是工作单元。含义:如果数据等只存在这样的时间,那么这不是问题,因为您将永远不会在保存后尝试访问数据。随后(在不同的上下文中)加载数据也应该没问题,因为 id 在生命周期中不会改变。

或者:删除此哈希/等式。

于 2010-04-13T05:10:21.820 回答
1

非密封类不应该实现IEquatable<T>,因为确保一个派生类覆盖Object.Equals()并以一致的方式Object.GetHashCode()实现的唯一方法是接口实现调用虚方法。由于 的 唯一目的是避免调用的开销,并且在未密封类上的安全实现无法避免调用它,因此这样的实现将毫无用处。IEquatable<BaseType>Object.GetHashCode()Object.Equals(Object)IEquatable<T>Object.Equals(Object)IEquatable<T>

此外,我强烈建议不要对任何可变类类型进行任何覆盖Object.Equals(或实现)。IEquatable<T>对于结构体,无论是否可变,覆盖Object.EqualsandObject.GetHashCode并实现都是有好处的IEquatable<theirOwnType>,因为存储为例如Dictionary键的结构体的字段将是不可变的,即使结构体类型公开了可变的公共字段。

于 2012-08-27T17:46:58.330 回答