Question

I have an class called WorkflowTask that contains a TaskProperties class property. There is a number of subclasses for TaskProperties mapped using JoinedSubclassMapping (such as DeliveryTaskProperties).

I need to execute a NHibernate Query such as the following to get a List of the workflow tasks that I need to handle:

NHibernateSession.Query<WorkflowTask>().Where(x => (x.WorkflowTaskStatus ==  WorkflowTask.WorkflowTaskStatuses.New && x.TaskProperties.UserAssignedTo=="System")).ToList<WorkflowTask>();

When iterating through this list I notice that the correct subclass of TaskProperties is identified. However when I try to cast the wt.TaskProperties to DeliveryTaskProperties to access its data I get an invalid cast exception. The only way I can get this to work is to try to load the task properties entity again by specifying the exact subclass:


The following works and I can cast to the DeliveryTaskProperties class:

wt.TaskProperties = NHibernateSession.Load<DeliveryTaskProperties>(wt.TaskProperties.Id);

Immediate Window:

{Workflow.Entities.DeliveryTaskProperties}

[DeliveryTaskPropertiesProxy]: {Workflow.Entities.DeliveryTaskProperties}

base: {Workflow.Entities.DeliveryTaskProperties}

UserAssignedTo: "system"


This doesn't Work and I get an invalid cast exception:

wt.TaskProperties = NHibernateSession.Load<TaskProperties>(wt.TaskProperties.Id);

Immediate Window:

{Workflow.Entities.DeliveryTaskProperties}

[TaskPropertiesProxy]: {Workflow.Entities.DeliveryTaskProperties}

base: {Workflow.Entities.DeliveryTaskProperties}

UserAssignedTo: "system"


Classes Mapping:

     public class WorkflowTaskMapping : BaseWorkflowEntityMapping<WorkflowTask>
{
    public WorkflowTaskMapping()
    {

        this.Property(x => x.TaskPropertiesId, map =>
        {
            map.Column("TaskPropertiesId");
            map.Insert(false);
            map.Update(false);
            map.NotNullable(true);
        });

        this.ManyToOne<TaskProperties>(x => x.TaskProperties, map =>
        {
            map.Column("TaskPropertiesId");
            map.Cascade(Cascade.All);
            map.NotNullable(true);
            map.ForeignKey("WFTaskProperties_WFTask_FK");
        });

        this.Property(x => x.WorkflowTaskStatus, map => map.NotNullable(true));
    }
}

        public class TaskPropertiesMapping : BaseWorkflowEntityMapping<TaskProperties>
{
    public TaskPropertiesMapping()
    {
        this.Property(x => x.UserAssignedTo, map => map.NotNullable(true));
    }
}

        public class DeliveryTaskPropertiesMapping : JoinedSubclassMapping<DeliveryTaskProperties>
{
    public DeliveryTaskPropertiesMapping()
    {

        this.Key(x => { x.Column("Id"); x.ForeignKey("DelivTask_TaskProperties_FK"); });
        this.Property(x => x.DeliveryAddress, map => map.NotNullable(true));
        this.Property(x => x.Deadline, map => map.NotNullable(true));
        this.Property(x => x.DeliveryOnDeadline, map => map.NotNullable(true));

    }

}

Is there a way to load the subclass data correctly when loading the WorkflowTask entity and without having to specify the exact subclass type?

Was it helpful?

Solution

OK, I figured it out. Although it wasn't very clear on other posts I read dealing with similar issues it seems that Eager Fetching did the trick for me.

If I change my query and add fetching like this:

               NHibernateSession.Query<WorkflowTask>().Where(x => (x.WorkflowTaskStatus == WorkflowTask.WorkflowTaskStatuses.New && x.TaskProperties.UserAssignedTo == "System")).Fetch(x => x.TaskProperties).ToList<WorkflowTask>();

Then nhibernate actually loads the subclass in memory although the type remains that of the base class. This allows for later casting to the subclass to access its properties.

OTHER TIPS

Im not sure if is this what you need:

TaskProperties tpAlias = null;

var workflowTasks = NHibernateSession.QueryOver<WorkflowTask>()
    .Left.JoinAlias(x => x.TaskProperties, () => tpAlias)
    .Where(x => (x.WorkflowTaskStatus ==  WorkflowTask.WorkflowTaskStatuses.New 
           && x.TaskProperties.UserAssignedTo == "System"))
    .List();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top