views:

644

answers:

3

I have a proxy for a lazy entity which has been created in the session by loading a child entity. A subsequent fetch on the parent entity only returns the NH proxy. I need the actual instance to check the type (the entity has joined subclasses). I must be missing something, but I can't find a way to do this. Session.Refresh(proxy) does not appear to help, nor does any flavour of HQL that I've tried.

Can anyone help?

A: 

Since the proxy is derived from the entity class, you can probably just check entity.GetType().BaseType to get your defined type.

Paul Alexander
No, he can't. "the entity has joined subclasses". This means, that the proxy will always be derived from BASE class of this hierarchy, not concrete class (at the time nhibernate creates the proxy it doesn't know what the type of entity is!). Sam wants to check which of subtypes it is.
maciejkow
That makes sense...missed that.
Paul Alexander
+2  A: 

To force a proxy to be fetched from the database, you can use the NHibernateUtil.Initialize(proxy) method, or access a method/property of the proxy.

var foo = session.Get<Foo>(id);
NHibernateUtil.Initialize(foo.Bar);

To check if an object is initialized or not, you can use the NHibernateUtil.IsInitialized(proxy) method.

Update:

To remove an object from the session cache, use the Session.Evict(obj) method.

session.Evict(myEntity);

Info about Evict and other methods for managing the session cache can be found in chapter 14.5 of the NHibernate docs.

Erik Öjebo
No, this doesn't work - it looks like this method is intended to populate an existing proxy with data, not load a new instance of the correct type. I guess I'm after a mechanism to clear a specific proxy object from the cache (without clearing the whole session) so that when I do a Get it returns the correct type.
Sam
Ok, I've updated the answer with info about how to remove an object from the session cache.
Erik Öjebo
That did the trick Erik, thanks - I'm not sure how I missed that one.
Sam
Glad I could help out
Erik Öjebo
+6  A: 

In my opinion, rather then solving this problem, you should rather rethink your design. Are you absolutely sure, that you can't use polymorphism in this situation - either directly make entity responsible for operation you're trying to perform or use visitor pattern. I came across this issue few times and always decided to change design - it resulted in clearer code. I suggest you do the same, unless you're absolutely sure that relying on type is the best solution.

The problem

In order to have example with at least some resemblance to the real world, let's suppose you have following entities:

public abstract class Operation
{
    public virtual DateTime PerformedOn { get; set; }
    public virtual double Ammount { get; set; }
}

public class OutgoingTransfer : Operation
{
    public virtual string TargetAccount { get; set; }
}

public class AtmWithdrawal : Operation
{
    public virtual string AtmAddress { get; set; }
}

It'd naturally be a small part of much larger model. And now you're facing a problem: for each concrete type of Operation, there's a different way to display it:

private static void PrintOperation(Operation operation)
{
    Console.WriteLine("{0} - {1}", operation.PerformedOn,
                      operation.Ammount);
}

private static void PrintOperation(OutgoingTransfer operation)
{
    Console.WriteLine("{0}: {1}, target account: {2}",
                      operation.PerformedOn, operation.Ammount,
                      operation.TargetAccount);
}

private static void PrintOperation(AtmWithdrawal operation)
{
    Console.WriteLine("{0}: {1}, atm's address: {2}",
                      operation.PerformedOn, operation.Ammount,
                      operation.AtmAddress);
}

Simple, overloaded methods will work in simple case:

var transfer = new OutgoingTransfer
               {
                   Ammount = -1000,
                   PerformedOn = DateTime.Now.Date,
                   TargetAccount = "123123123"
               };

var withdrawal = new AtmWithdrawal
                 {
                     Ammount = -1000,
                     PerformedOn = DateTime.Now.Date,
                     AtmAddress = "Some address"
                 };

// works as intended
PrintOperation(transfer);
PrintOperation(withdrawal);

Unfortunately, overloaded methods are bound at compile time, so as soon as you introduce an array/list/whatever of operations, only a generic (Operation operation) overload will be called.

Operation[] operations = { transfer, withdrawal };
foreach (var operation in operations)
{
    PrintOperation(operation);
}

There are two solutions to this problem, and both have downsides. You can introduce an abstract/virtual method in Operation to print information to selected stream. But this will mix UI concerns into your model, so that's not acceptable for you (I'll show you how can you improve this solution to meet your expectations in a moment).

You can also create lots of ifs in form of:

if(operation is (ConcreteType))
   PrintOperation((ConcreteType)operation);

This solution is ugly and error prone. Every time you add/change/remove type of operation, you have to go through every place you used these hack and modify it. And if you miss one place, you'll probably only be able to catch that runtime - no strict compile-time checks for some of errors (like missing one subtype).

Furthermore, this solution will fail as soon as you introduce any kind of proxy.

How proxy works

The code below is VERY simple proxy (in this implementation it's same as decorator pattern - but those patterns are not the same in general. It'd take some additional code to distinguish those two patterns).

public class OperationProxy : Operation
{
    private readonly Operation m_innerOperation;

    public OperationProxy(Operation innerOperation)
    {
        if (innerOperation == null)
            throw new ArgumentNullException("innerOperation");
        m_innerOperation = innerOperation;
    }


    public override double Ammount
    {
        get { return m_innerOperation.Ammount; }
        set { m_innerOperation.Ammount = value; }
    }

    public override DateTime PerformedOn
    {
        get { return m_innerOperation.PerformedOn; }
        set { m_innerOperation.PerformedOn = value; }
    }
}

As you can see - there is only one proxy class for whole hierarchy. Why? Because you should write your code in a way that doesn't depend on concrete type - only on provided abstraction. This proxy could defer entity loading in time - maybe you won't use it at all? Maybe you'll use just 2 out of 1000 entities? Why load them all then?

So NHibernate uses proxy like on above (much more sophisticated, though) to defer entity loading. It could create 1 proxy per sub-type, but it would destroy whole purpose of lazy loading. If you look carefuly at how NHibernate stores subclasses you'll see, that in order to determine what type entity is, you have to load it. So it is impossible to have concrete proxies - you can only have the most abstract, OperationProxy.

Altough the solution with ifs it's ugly - it was a solution. Now, when you introduced proxies to your problem - it's no longer working. So that just leaves us with polymorphic method, which is unacceptable because of mixing UI responsibility to your model. Let's fix that.

Dependency inversion and visitor pattern

First, let's have a look at how the solution with virtual methods would look like (just added code):

public abstract class Operation
{
    public abstract void PrintInformation();
}

public class OutgoingTransfer : Operation
{
    public override void PrintInformation()
    {
        Console.WriteLine("{0}: {1}, target account: {2}",
                      PerformedOn, Ammount, TargetAccount);
    }
}

public class AtmWithdrawal : Operation
{
    public override void PrintInformation()
    {
        Console.WriteLine("{0}: {1}, atm's address: {2}",
                          PerformedOn, Ammount, AtmAddress);
    }
}

public class OperationProxy : Operation
{
    public override void PrintInformation()
    {
        m_innerOperation.PrintInformation();
    }
}

And now, when you call:

Operation[] operations = { transfer, withdrawal, proxy };
foreach (var operation in operations)
{
    operation.PrintInformation();
}

all works as a charm.

In order to remove this UI dependency in model, let's create an interface:

public interface IOperationVisitor
{
    void Visit(AtmWithdrawal operation);
    void Visit(OutgoingTransfer operation);
}

Let's modify model to depend on this interface:

And now create an implementation - ConsoleOutputOperationVisitor (I have deleted PrintInformation methods):

public abstract class Operation
{
    public abstract void Accept(IOperationVisitor visitor);
}

public class OutgoingTransfer : Operation
{
    public override void Accept(IOperationVisitor visitor)
    {
        visitor.Visit(this);
    }
}

public class AtmWithdrawal : Operation
{
    public override void Accept(IOperationVisitor visitor)
    {
        visitor.Visit(this);
    }
}

public class OperationProxy : Operation
{
    public override void Accept(IOperationVisitor visitor)
    {
        m_innerOperation.Accept(visitor);
    }
}

What happens here? When you call Accept on operation and pass a visitor, implementation of accept will be called, where appropriate overload of Visit method will be invoked (compiler can determine type of "this"). So you combine "power" of virtual methods and overloads to get appropriate method called. As you can see - now UI reference here, model only depends on an interface, which can be included in model layer.

So now, to get this working, an implementation of the interface:

 public class ConsoleOutputOperationVisitor : IOperationVisitor
 {
    #region IOperationVisitor Members
    public void Visit(AtmWithdrawal operation)
    {
        Console.WriteLine("{0}: {1}, atm's address: {2}",
                          operation.PerformedOn, operation.Ammount,
                          operation.AtmAddress);
    }

    public void Visit(OutgoingTransfer operation)
    {
        Console.WriteLine("{0}: {1}, target account: {2}",
                          operation.PerformedOn, operation.Ammount,
                          operation.TargetAccount);
    }

    #endregion
}

And code:

Operation[] operations = { transfer, withdrawal, proxy };
foreach (var operation in operations)
{
    operation.Accept(visitor);
}

I'm well aware that this isn't a perfect solution. You'll still have to modify the interface and visitors as you add new types. But you get compile time checking and will never miss anything. One thing that would be really hard to achieve using this method is to get pluggable subtypes - but I'm not convinced this is a valid scenario anyway. You'll also have to modify this pattern to meet your needs in concrete scenario, but I'll leave this to you.

maciejkow
Basically I'm trying to display a different (windows) form for each subclass, when a row is double-clicked in a list. I'm open to suggestions for a better design (that doesn't involve presentation code in the domain model).
Sam
Can I get you to elaborate on the polymorphic solution? My main issue is that the proxy is derived from the base type, not the subclass, so I'm not clear how it's going to perform the correct subclass's implementation of the operation.
Sam
I've edited my answer.
maciejkow
Sam