2

I have a project where we are using only named queries to access the database. Recently we have created new entities that we were planing to map following the table per Subclass pattern, so we created the mappings following the documentation and everything seems good, except that we cannot find how to define the table aliases in the named queries in order to load each subclass.

This is what we have done so far:

Entities:

public class Gear 
{
    public virtual string Name { get; set; }

    public virtual string Slug { get; set; }
}

public class Pedal : Gear
{
    public virtual PedalTypeEnum PedalType { get; set; }
}

Mappings:

public class GearMap : ClassMap<Gear>
{
    public GearMap()
    {
        Table("[Gear]");

        Id(m => m.Id).Column("Id");
        Map(m => m.Name).Column("[Name]");
        Map(m => m.Slug).Column("[Slug]");
    }
}


public class PedalMap : SubclassMap<Pedal>
{

    public PedalMap() 
    {

        Table("[Pedal]");
        KeyColumn("[Gear_Id]");

        Map(m => m.PedalType).Column("PedalType").CustomType(typeof(PedalTypeEnum));


    }
}

And the query that we are trying to execute is this one:

<sql-query name="myquery" >
<return alias="[Gear]" class="Gear" />
<![CDATA[
    SELECT 
        {[Gear].*},
FROM 
        [Gear] {[Gear]}
]]>
</sql-query>

And this results in the following SQL generated by nhibernate:

SELECT 
     [Gear].[Id] as column1_12_0_, 
     [Gear].[Name] as column3_12_0_, 
     [Gear].[Slug] as column4_12_0_,          
     [Gear]_1_.PedalType as PedalType13_0_, 
     case 
        when [Gear]_1_.[Gear_Id] is not null then 1 
        when [Gear].[Id] is not null then 0 end as clazz_0_
FROM 
        [Gear] [Gear] 

As you can see it detects the subclasses correctly and tries to load the field PedalType that only belongs to the subclass but as there is no table with the alias [Gear]_1_. the query fails...

We have tried to make the join with the pedal table, but we are unable to find the right way to set the alias in a way that it translates to [Gear]_1_.

Any help?

Drevak
  • 867
  • 3
  • 12
  • 26

1 Answers1

4

This worked for me:

<sql-query name="myquery" >
  <return alias="Gear" class="Gear" />
  SELECT {Gear.*}
  FROM Gear {Gear}
  LEFT JOIN Pedal Gear_1_ on Gear.Id = Gear_1_.Gear_Id
</sql-query>

But of course you could have just used HQL instead of SQL:

<query name="myhqlquery">
  from Gear
</query>

However... I must say this is a very inefficient usage of NHibernate. You are fighting very hard against the framework instead of taking advantage of its flexibility.

Diego Mijelshon
  • 52,548
  • 16
  • 116
  • 154
  • sorry, could you explain why this is going against the framework? I'm using SQL as it seems the best way to tweak the sql queries for maximum performance while preserving all the flexibility of the framework :) – Drevak Jun 19 '12 at 20:16
  • It's absolutely fine to hand-craft SQL **when needed**. But forcing that for every query is a waste of time. And, in cases like this, you need a lot of effort for something that would work out of the box with all other methods (and it will likely break under many circumstantes). Put another way: what would you optimize here exactly? Does your **actual profiling** show those optimizations are necessary? – Diego Mijelshon Jun 19 '12 at 20:56
  • The idea behind using an ORM is, precisely, NOT having to hand-craft SQL, while taking advantage of change tracking, identity maps, and other features the ORM offers. SQL query capabilities are offered for flexibility, because *sometimes* you have queries that aren't easy to express with HQL, LINQ or Criteria. But most of the time other methods are easier to code and maintain. – Diego Mijelshon Jun 19 '12 at 20:59
  • I'm using change tracking :) and all the features that nhibernate offers. Using named queries with standard SQL is perfecty fine as long as I let Nhibernate inject the aliases. You can see that in the documentation. And no, i'm not doing any premature optimization, but I need to use fulltext and spatial indexes in many of the queries. And on top of that, all want the queries as much ORM independant as I can. – Drevak Jun 19 '12 at 23:06
  • Further more, it might be a waste of time FOR YOU. For me is just much faster to code and debug plain old SQL and the copy it to an XML file than testing and debugging that whatsoever messy SQL code that nhibernate generates :) – Drevak Jun 19 '12 at 23:09
  • And, this is just an example, of course there is nothing to optimze here, but as you can guess...our queries are much more complex that this :) – Drevak Jun 19 '12 at 23:12
  • Moreover, the other inheritance methods work perfectly fine with raw sql, so i doubt this has something to do with anything that you are saying. – Drevak Jun 19 '12 at 23:20
  • 1
    Alright, whatever works for you. But for polymorphic queries in particular, hacking NH's internal conventions is probably not the best idea in the long term. – Diego Mijelshon Jun 20 '12 at 00:07
  • Correct, that's why I'm here, and the reason of the bounty. Why table per subclass inheritance cannot be loaded using "aliased" plain SQL while other inheritance mappings can? Why do I need to hack the alias to make it work? Sounds like a problem in the framework, not in my aproach (which is perfectly valid according to the documentation). The architecture of the project is irrelevant in this case. – Drevak Jun 20 '12 at 00:53
  • 1
    I usually turn those questions around. Have you thought that *maybe* you're the only person in the world trying to do that? I'm not saying your architecture is invalid, but it's entirely possible that, since nobody else uses it, nobody took the time to write NHibernate code to support it. That's what's great about open source: you can get the NH source, create a new injection macro that expands to the full joined-subclass statement and contribute it to the community. – Diego Mijelshon Jun 20 '12 at 12:07