I've set up a test scenario to replicate your issue. I have indeed
replicated it. I've also got a workaround set up and going that
resolves the problem. Here's why this doesn't work.
IEquatable<T> only works when doing comparisons using the .Equals(T
obj) overload. The PersistenceSpecification.CheckProperty() stores the
values into a List as Objects. When VerifyTheMappings() is called, it
runs through and does an Equals(object) call on each value in the
collection. Here it is from fluent's source:
public void VerifyTheMappings()
{
...
...
_allProperties.ForEach(p => p.CheckValue(second));
}
internal virtual void CheckValue(object target)
{
...
areEqual = _propertyValue.Equals(actual);
...
...
}
If you notice, _propertyValue.Equals(actual) is actually calling the
Equals(object obj), not the IEquality<T> overload. This falls back on
referencial equality (or ID Equality if working within an NHibernate
session with two retrieved objects, which isn't the case here). This
returns false, as expected.
There's two ways to get around your issue.
1.) In general, when working with NHibernate, it's considered a best
practice to override Equals and GetHashCode in your Password class and
set it to business rules for equality, like so:
public override bool Equals(object obj)
{
Password other = obj as Password;
if (other == null)
{ return false; }
return this.password == other.password;
}
public override int GetHashCode()
{
return password.GetHashCode();
}
--
This works for me with the PersistenceSpecification, and I was able to
get the test passing with just that change.
Option 2.) A PersistenceSpecification constructor allows you to pass
in your own custom IEqualityComparer as an overload. If passed in, the
IEqualityComparer.Equals(obj1, obj2) will be called instead of
obj1.Equals(obj2).
I hope that helps :)
On Mar 26, 7:38 pm, cprieto <[email protected]> wrote:
> I found a weird behavior of PersistenceSpecification testing
> components with IEquatable implemented (when using hbm mappings).
>
> Is it this the normal? do I miss something? Lastly tested on Fluent
> NHibernate r432
>
> Thanks for your help!!!
>
> I did a simple test to show my point:
>
> public class Password : IEquatable<Password>
> {
> readonly string password;
>
> protected Password() {}
>
> public Password(string password)
> {
> this.password = password;
> }
>
> public bool Equals(Password other)
> {
> return password.Equals(other.password);
> }
> }
>
> public class User
> {
> public int Id { get; protected set; }
> public Password Password { get; protected set; }
> }
>
> public class DbContext
> {
> protected ISessionSource SessionSource;
>
> public DbContext()
> {
> var configuration =
> FluentNHibernate.Cfg.Fluently.Configure().Database
> (SQLiteConfiguration.Standard.UsingFile("test.db")).Mappings(
> x => x.HbmMappings.AddFromAssemblyOf<User>());
>
> SessionSource = new SessionSource(configuration);
> }
> }
>
> public class UserMappingFacts : DbContext
> {
> public UserMappingFacts()
> {
> SessionSource.BuildSchema();
> }
>
> [Fact] // Pass as expected
> public void Password_must_be_equal_with_same_password()
> {
> var password_one = new Password("password");
> var password_two = new Password("password");
> var password_three = new Password("other.password");
>
> Assert.Equal(password_one, password_two);
> Assert.NotEqual(password_one, password_three);
> }
>
> [Fact] // Fails!!!
> public void User_is_well_mapped()
> {
> new PersistenceSpecification<User>(SessionSource)
> .CheckProperty(x => x.Password, new Password
> ("password"))
> .VerifyTheMappings();
> }
> }
>
> ///// HBM file
> <?xml version="1.0" encoding="utf-8" ?>
> <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-
> lazy="false" assembly="ClassLibrary2" namespace="ClassLibrary2">
> <class name="User">
> <id name="Id">
> <generator class="native" />
> </id>
> <component name="Password">
> <property name="password" access="field" not-null="true" />
> </component>
> </class>
> </hibernate-mapping>
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Fluent NHibernate" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/fluent-nhibernate?hl=en
-~----------~----~----~----~------~----~------~--~---