diff --git a/src/NHibernate/Engine/EntityKey.cs b/src/NHibernate/Engine/EntityKey.cs index e6646f1fda5..443ca3e2d40 100644 --- a/src/NHibernate/Engine/EntityKey.cs +++ b/src/NHibernate/Engine/EntityKey.cs @@ -3,10 +3,10 @@ using System.Security; using NHibernate.Impl; using NHibernate.Persister.Entity; -using NHibernate.Type; namespace NHibernate.Engine { + //TODO 6.0: Remove IDeserializationCallback interface /// /// A globally unique identifier of an instance, consisting of the user-visible identifier /// and the identifier space (eg. tablename) @@ -17,15 +17,14 @@ public sealed class EntityKey : IDeserializationCallback, ISerializable, IEquata private readonly object identifier; private readonly IEntityPersister _persister; // hashcode may vary among processes, they cannot be stored and have to be re-computed after deserialization - [NonSerialized] - private int? _hashCode; + private readonly int _hashCode; /// Construct a unique identifier for an entity class instance public EntityKey(object id, IEntityPersister persister) { identifier = id ?? throw new AssertionFailure("null identifier"); _persister = persister; - _hashCode = GenerateHashCode(); + _hashCode = GenerateHashCode(persister, id); } private EntityKey(SerializationInfo info, StreamingContext context) @@ -34,6 +33,7 @@ private EntityKey(SerializationInfo info, StreamingContext context) var factory = (ISessionFactoryImplementor) info.GetValue(nameof(_persister.Factory), typeof(ISessionFactoryImplementor)); var entityName = (string) info.GetValue(nameof(EntityName), typeof(string)); _persister = factory.GetEntityPersister(entityName); + _hashCode = GenerateHashCode(_persister, identifier); } public bool IsBatchLoadable => _persister.IsBatchLoadable; @@ -66,26 +66,16 @@ public bool Equals(EntityKey other) public override int GetHashCode() { - // If the object is put in a set or dictionary during deserialization, the hashcode will not yet be - // computed. Compute the hashcode on the fly. So long as this happens only during deserialization, there - // will be no thread safety issues. For the hashcode to be always defined after deserialization, the - // deserialization callback is used. - return _hashCode ?? GenerateHashCode(); + return _hashCode; } - /// - public void OnDeserialization(object sender) - { - _hashCode = GenerateHashCode(); - } - - private int GenerateHashCode() + private static int GenerateHashCode(IEntityPersister persister, object id) { int result = 17; unchecked { - result = 37 * result + RootEntityName.GetHashCode(); - result = 37 * result + _persister.IdentifierType.GetHashCode(identifier, _persister.Factory); + result = 37 * result + persister.RootEntityName.GetHashCode(); + result = 37 * result + persister.IdentifierType.GetHashCode(id, persister.Factory); } return result; } @@ -96,11 +86,15 @@ public override string ToString() } [SecurityCritical] - public void GetObjectData(SerializationInfo info, StreamingContext context) + void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue(nameof(Identifier), identifier); info.AddValue(nameof(_persister.Factory), _persister.Factory); info.AddValue(nameof(EntityName), EntityName); } + + [Obsolete("IDeserializationCallback interface has no usages and will be removed in a future version")] + public void OnDeserialization(object sender) + {} } }