I am using Entity Framework in my application.
I implemented with the partial class of an entity the IEquatable<T>
interface:
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
Now in my code I use it this way:
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
Note (I checked in the debugger visualizer) that the EntityCollection class stores its entities in HashSet so it has to do with the GetHashCode function, I want it to depend on the ID so entities are compared by their IDs.
The problem is that when I hit save, the ID changes from 0 to its db value. So the question is how can I have an equatable object, being properly hashed.
Please help me find what's wrong in the GetHashCode function (by ID) and what can I change to make it work.
Thanks a lot.
You've used a mutable field (AddressId
) as part of the hash - that is unfortunately doomed. By which I mean: when you add it, the AddressId
is 0? -1? it doesn't matter what exactly, but it isn't the final id - and it is stored with this key / hash. When you save it, the actual id (the IDENTITY
column from the database) is updated into the object.
Quite simply, you cannot reliably hash against this value if it can change when it is part of a dictionary. One possible workaround would be to consider the unit-of-work, i.e. an insert is a unit-of-work. Meaning: if the data etc only lives as long as this, then it is a non-issue as you will never attempt to access the data after saving it. Subsequently (in a different context) loading the data should be fine too, as the id doesn't then change during the lifetime.
Alternatively: drop this hash/equality.