I have an Entity that doesn't override any of the equality members\operators.
When comparing two proxies of them (I got them from the Nhibernate session
) the result changes according to the equality method:
- ReferenceEquals(first, second) - false.
- first == second - false
- Equals(first, second) - true.
This is even more weird as they both exist in the same session context and according to the Nhibernate docs:
NHibernate only guarantees identity ( a == b , the default
implementation of Equals()) inside a single ISession!`
And:
The instance is currently associated with a persistence context. It
has a persistent identity (primary key value) and, perhaps, a
corresponding row in the database. For a particular persistence
context, NHibernate guarantees that persistent identity is equivalent
to CLR identity (in-memory location of the object).
So why not all of the equality methods return true?
Update:
I get the enteties this way, Query the session for ChildEntity and get the Parents Entities with Linq's select
, similar to this:
var childs = session.Query<Child>();
var parents = childs.Select(x => x.ParentEntity).ToList();
Edit
You might be using a struct? See below
I suppose reference types show the behaviour you expect:
public class Program {
class X { int x,y; }
public static void Main(string[] args)
{
X a = new X();
X b = new X();
System.Console.WriteLine(a == b);
System.Console.WriteLine(a.Equals(b));
System.Console.WriteLine(Equals(a,b));
System.Console.WriteLine(ReferenceEquals(a,b));
} }
Prints:
False
False
False
False
For structs, things are different (commeting out the a==b
test, which doesn't compile for structs:)
public class Program {
struct X { int x,y; }
public static void Main(string[] args)
{
X a = new X();
X b = new X();
//System.Console.WriteLine(a == b);
System.Console.WriteLine(a.Equals(b));
System.Console.WriteLine(Equals(a,b));
System.Console.WriteLine(ReferenceEquals(a,b));
} }
Output:
True
True
False
Rationale:
The default implementation of Equals() comes from class ValueType
, which is implicit base class of all value types. You may override this implementation by defining your own Equals() method in your struct. ValueType.Equals()
always returns false when one compares objects of different (dynamic) types. If objects are of the same type, it compares them by calling Equals()
for each field. If any of these returns false, the whole process is stopped, and final result is false. If all field-by-field comparisons return true, final result is true
If ReferenceEquals
returns false, you are clearly comparing two different instances.
Equals might still be true if it's overridden, but I don't think that's where the actual problem is.
I'd like to know how you're mapping and getting those objects, because as the docs say, you can never get two different objects of the same type representing the same row in the same session.
After I get childs
from the session I Merge them with the session.
var childs = session.Query<Child>();
// Do some stuff
foreach (var child in childs)
{
session.Merge(child);
}
var parents = childs.Select(x => x.ParentEntity).ToList();
It appear that the merge detached the entity from the session and return a new Proxy attached to the session.
It can be fixed with
var newChild = (Child)session.Merge(child);
// Or:
session.Update(child); // (We have session.Clear() in our tests so I can't use this because it makes troubles when you update detached Entity