Geeks With Blogs
// ThomasWeller C#/.NET software development, software integrity, life as a freelancer, and all the rest

A few days ago, I talked about a problem, that using an ORM like NHibernate could bring, when there's inheritance and lazy loading around (please refer to this post). Unfortunately, the example in this post turned out to be somewhat unclear. So here's a short follow-up with another example, that hopefully underpins my arguments a bit more precisely.

The original example gave the impression that the problem occurs only when we would try to typecast around in some way or the other, which is in most cases problematic in itself. While this was absolutely not what I had in mind, I must admit that one could easily come to that suggestion from reading the code. Unfortunately, the described problem is not only significant for typecasting issues, but - far more general - for everything that somehow relies on type information.

So let's see an example for that. First, I implemented equality-comparison on the original Person class:

/// <summary>Book author is a single ('real') person.</summary>

/// <remarks>Implements equality based on its <see cref="Author.Id"/>.</remarks>

public class Person : Author, IEquatable<Person>

{

    public override bool Equals(object obj)

    {

        return this.Equals(obj as Person);

    }

    public virtual bool Equals(Person other)

    {

        if (object.ReferenceEquals(null, other)) return false;

        if (object.ReferenceEquals(this, other)) return true;

 

        return this.Id == other.Id;

    }

}

 Quite trivial and intuitive, and 100% along the lines of standard .NET programming. Most developers have seen and written such code many times. To see the problem with that, look at the following test:

[Test]

public void AnAuthorShouldRemainEqualToItselfAfterSavingAndReloading()

{

    Author goethe = new Person { Id = 1, Line = "Goethe" };

    Book book = new Book { Name = "Faust", Author = goethe };

 

    Assert.AreEqual(goethe, book.Author); // pass

 

    using (ISession session = this.sessionFactory.OpenSession())

    {

        // Persist the book and remove it from session cache (thus

        // effectively simulating two different sessions...).

        object id = session.Save(book);

        session.Evict(book);

 

        // Reload the book and compare its author to its original instance.

        Book savedAndReloadedBook = session.Get<Book>(id);

        Console.WriteLine("Just to see lazy loading happening...");

 

        Assert.AreEqual(goethe, savedAndReloadedBook.Author); // fail !

    }

}

The result for that test is:

EqualityTestResult

So one and the same equality comparison gives different results here, although we did nothing obviously wrong, and no polymorphic casting is done in any way! (And no, it has also nothing to do with the Id value...).

Related problems might occur for example, if one is trying to implement IComparable<Person>, and many other use case scenarios can be imagined, where the domain's behavior suddenly will be altered under the hood for no obvious reason! I consider that a big problem for the general acceptance of ORMs in software architecture...

Posted on Thursday, September 10, 2009 7:53 AM NHibernate , Architecture and Design | Back to top


Comments on this post: Lazy loading, Inheritance, and Persistence ignorance (part 1.5)

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © Thomas Weller | Powered by: GeeksWithBlogs.net