4

Several sources state that NHibernate can not use identity with table per concrete class and union-subclasses. Is this true, and what is the exact reason behind this ?

Denis Biondic
  • 7,943
  • 5
  • 48
  • 79

2 Answers2

4

It's simple. The POID must be unique across all instances of a root entity type.

Consider the following example:

abstract class Vehicle { ... }
class Car : Vehicle { ... }
class Truck : Vehicle { ... }

If you were to retrieve a Vehicle whose concrete type you don't know:

var carOrTruck = session.Get<Vehicle>(vehicleId);

...and there were both a Car and a Truck with that Id (which is possible with identity), which one would NHibernate return? (there are more complex cases, but this illustrates one possible issue)

Therefore, for table-per-concrete-class (a pretty bad strategy if you ask me), NHibernate needs a generator that guarantees uniqueness across subclasses.

Diego Mijelshon
  • 52,548
  • 16
  • 116
  • 154
  • What would happen if you call the same session.Get in case of implicit polymorphism (table-per-concrete without union, just plain class mappings), where each table has its own identity ? – Denis Biondic Feb 02 '12 at 20:06
  • I'm referring to this question as well: http://stackoverflow.com/questions/9097933/any-real-use-for-table-per-concrete-class-with-implicit-polymorphism – Denis Biondic Feb 02 '12 at 20:07
1

Why do you say so? I think I had several scenarios like that. Also this blog entry states the same.

To sum up comments below: as in the example that Ayende has, if you query for all root types (so "Select Party") you can get duplicates for ID. That fact along with UNION characteristic (returns only distinct records) could give you unexpected results (missing records). That's why you cannot use identity but rather hilo which allows nhibernate to avoid duplicates.

IamDeveloper
  • 5,156
  • 6
  • 34
  • 50
  • That same source states: "Note that it is not possible to use identity with union-subclasses, so I switched to hilo," – Denis Biondic Feb 02 '12 at 10:26
  • You're true. I suppose I used "table per subclass" approach – IamDeveloper Feb 02 '12 at 10:42
  • Well, I think it's because you simply cannot guarantee to not have collisions there. Take a look at the source and look for "Select Party" example. With generator you could end up having repeated ids. – IamDeveloper Feb 02 '12 at 10:44
  • Exactly, but by not using union-sublass you can use identity, therefore, you can have repeated Ids as well, so that isn't a problem with NHibernate. So, what is the difference here with union-subclass? I presume it is the issue with something specific about SQL UNIONS or something, I'm just not sure... – Denis Biondic Feb 02 '12 at 11:00
  • No, it's not the same. With "table per subclass", cause I think you refer to this, a record is first inserted into abstract table then it's propagated to subclass tables. The parent table contains real identity column, tha child tables don't have pk, just fk. – IamDeveloper Feb 02 '12 at 11:06
  • No, I don't mean table per subclass, you can't even use union-subclass with that strategy, you use join-subclass, it is all clear with that strategy and reasons why they share keys, but here in table per concrete class when using implicit polimorphism (just plain old class mapping) you can have duplicate keys. When using union-subclass, several sources state that you can't. Now, with union-subclass you don't need parent table either (you mark it as abstract) and you practically have everything the same except the UNION query, so that is why I ask myself why you can't use identity as well... – Denis Biondic Feb 02 '12 at 12:04
  • 1
    I'm pretty sure I have answered why is it so. As in the example that Ayende has, if you query for all (so, "Select Party") you can get duplicates for ID. That fact along with UNION characteristic (returns only distinct records) could gave you unexpected results (missing records). Isn't that obvious? If on the other hand, yopu could somehow decide to use UNION ALL, you could get duplicates, which is really to be avoided with such approach. That's why it says you cannot use identity but rather hilo which allows nhibernate to avoid duplicates. – IamDeveloper Feb 02 '12 at 12:27
  • UNION will remove duplicate rows meaning it will remove rows that have all column values same, which means that this is a potential problem if this occurs, and this is the reason, yes ? – Denis Biondic Feb 02 '12 at 14:41