How to map a deeper hierarchy in nhibernate - nhibernate

I have this object graph, I want to map:
abstract Account (username, password, ...)
abstract Customer (shoppingcart, orders, roles)
IndividualCustomer (user data)
CorporateCustomer (different user data, company data)
Administrator (adminroles)
How can this be mapped against one table? (I know how to do this with an entity hierarchy that is only 1 level deep, just like in the docs, but this is different).
Anybody has an idea?
I asked the same in
http://groups.google.com/group/nhusers/browse_frm/thread/7a85cba0048c18d8?hl=en, but so far have not received a useful answer.

From what I see, it should be no different than one-level-deep hierarchy.
try this:
<hibernate-mapping>
<class
name="Account"
table="..." >
<property .../>
...
<subclass
name="Customer" >
<property ... "/>
...
</subclass>
<subclass
name="IndividualCustomer" >
<property ... "/>
...
</subclass>
...
</class>
I don't have NHibernate here, to check it, but it looks like it should work. You may also want to try to nest subclass elements if it doesn't.

nesting subclasses is against the xml schema, so my guess is, it will not work.
i probably would also have to nest the discriminator declaration, which also seems hackish.
and mapping it out flat... i pass a discriminator for an abstract class, that cannot ever be used because an abstract class cannot be instantiated. seems wrong, too.
but you are right, i will try it out some time. right now it seems like a better idea to me to let customer have an account, instead of being one.
thanks!

Related

Mapping inherited class with nhibernate hbm

I Have 2 classes of the same table.
one class, "Entity", contains properties x,y,z from table ENTITY
and the derived class, "ExtendedEntity" contains some more properties (collections - relations to other tables).
I want to map both of them but i couldn't find a way to map subclasses without using discriminator (I dont need one, sometimes i want to select the Entity object and sometimes the ExtendedEntity).
does anyone has any idea?
(I tried to map the ExtendedEntity by copying the Entity mapping and adding the new properties, but now when i want to get the Entity object it brings me ExtendedEntity).
Thanks!
Taking into account the first sentence of your question:
I Have 2 classes of the same table.
It means that there is only one table ("ENTITY"). If this is true, there do not have to be, and even should not be any inheritance, if no discriminator exists. If both entities will be related to all rows, then (instead of inheritance) we need laziness. And only one Entity profiting from the native NHibernate behavior: having lazy properties. And even more, to optimize some queries - the Projections could be used.
But again, my suggestion could be correct only if I do understand your scenario correctly: the two entities were introduced only to reduce workload; but both target all rows in one table.
The mapping for the only class
<class name="Entity" table="ENTITY" lazy="true">
<id name="ID" column="Entityd">
<generator class="native"></generator>
</id>
<!-- standard default always loaded properties -->
<property name="Code" />
<property name="Name" />
<!-- only if accessed, lazily loaded properties -->
<many-to-one lazy="proxy" name="Currency" column="CurrencyId" cascade="none" />
<property lazy="true" name="Image" column="ImageBinary" />
...
Having this mapping we can get first 5 Entities
var list = session.CreateCriteria<Entity>()
.SetMaxResults(5)
.List<Entity>();
And SQL statement generated will be:
SELECT TOP 5 this_.EntityId as EntityId3_1_
, this_.Code as Code3_1_
, this_.Name as Name3_1_
FROM ENTITY this_
And we can even reduce it with projections
var propertyList = NHibernate.Criterion.Projections.ProjectionList();
// projection properties
propertyList.Add(NHibernate.Criterion.Projections.Property("ID"));
propertyList.Add(NHibernate.Criterion.Projections.Property("Code"));
var projected = session.CreateCriteria<Entity>()
.SetMaxResults(5)
.SetProjection(propertyList)
.SetResultTransformer(new NHibernate.Transform
.AliasToBeanResultTransformer(typeof(Entity)))
.List<Entity>();
In this case is the SQL Select even smaller. If the ID and Code would be enough..
SELECT TOP 5 this_.Code as y0_
, this_.EntityId as y1_
FROM ENTITY this_
So, in case I read your question correctly, in your scenario solution would not be in inheritance but in NHibernate native laziness
NOTE: there could be ExtendedEntity derived from Entity even in this scenario. But not for inheritance via NHibernate mapping but for the Projections Transformation. Some properties from many-to-one properties could be projected this way...

Filter entities on mapping level in NHibernate

Let's say that I have and database table called People, and entity People. Let's say that I need a quick way to remove a subset of people from displaying everywhere in application. So I add IsDeleted column to People table, and set values in that column to 1.
In Entity Framework there's a mechanism that specifies that for instans of entities with value in column IsDeleted set to 1 shouldn't be fetched and mapping framework filters data automatically. Is is possible to achieve with NHibernate?
You can define where attribute in your class mapping.
where (optional) specify an arbitrary SQL WHERE condition to be used
when retrieving objects of this class
<class ... where="IsDeleted = 0">
If you are using Fluent NHibernate then just define this in mapping class:
Where("IsDeleted = 0");
NH's mapping by code should be similar to Fluent NHibernate's mapping.
You can create abstract class, e.g. PeopleBase, from which your People class will be derived and map your entity to it.
After that you can use discriminator like this (didn't check for correctness, but it should work):
<class name="YourNamespace.PeopleBase,YourNamespace" table="People">
// ...
<discriminator column="IsDeleted" type="boolean" />
// Properties...
// ...
<subclass name="YourNamespace.People, YourNamespace" discriminator-value="false">
</subclass>
</class>
In order to achieve what I wanted, I've created base class + two subclasses. This is the configuration:
subclasses with discriminator-value:
<subclass name="People" discriminator-value="null">
</subclass>
<subclass name="PeopleHistory" discriminator-value="not null">
<property name="MasterRowId" />
</subclass>
discriminator in base class:
<discriminator column="MasterRowId" />

NHibernate Composite Index, not a key

Still a n00b in NHibernate :(
I want to add a composite index to the hbm.xml of one of my POCOs, for performance purposes. It does not relate directly to a class, but rather two common values I will be querying against.
I think I need to do a <map></map> entry in the XML, but the XSD is asking for a class name on the composite-key element, and there is no direct relationship, per se... plus it's asking for more information than I think I would need to provide. How do I do this?
<map name="PropertyKeys">
<key>
<column name="StockID" />
<column name="PropertyName" />
</key>
<composite-index class="Something?">
<key-property name="What goes here?" />
</composite-index>
<what else goes here?>
</map>
Have you read this http://ayende.com/blog/4045/nhibernate-mapping-map It explains when you would use a map and further on it explains the composite-index
However without more background info it is not 100% certain that you need a map!

NHibernate - Lazy Loaded Collection

Should a lazy loaded collection in NHibernate ever give me a NullReferenceException? I'm getting an exception in a method like the following:
public void Test(ISession session, int id)
{
var entity = session.Load<MyEntity>(id);
entity.LazyLoadedCollection.Add(SomeItem);
}
The call to LazyLoadedCollection is throwing. My mapping looks like:
<bag lazy="true" table="MyTable">
<key>
<column name="LazyLoadedCollection" />
</key>
<many-to-many class="LazyLoadedItem">
<column name="LazyLoadedItemId" />
</many-to-many>
</bag>
Is this the expected behavior in NHibernate?
It's hard to say without seeing your class, but one thing you may not have realized is that you need to populate each collection in your class's constructor.
NHibernate will replace these collections with its own at certain times, but you still need to make sure they're initially populated with a HashedSet<T>, List<T>, or something else depending on the interface you're using.
No it's not. This is a not a good way to ask a question on the internet.
And it's really impossible to give you a direction what to do if you don't post the code throwing the exception and tell us where the exception comes from.

Hibernate mappings: Splitting up the file

Alright, I've got a quick question. I'm currently working with a legacy database, so I can't change around much. The database revolves around a single type, the entity. All other relevant data (except for customizable lists etc.) 'inherit' from this.
I'm mapping this with a joined subclass approach, which is working fine. The problem however, is that my mapping file is reaching hideous proportions. I would like to split up the file in multiple separate files, but I'm not sure if this is possible and how to approach this problem. I've read through the Hibernate docs on the official site, but couldn't find anything.
To clarify, mappings look like this:
<class name="..." table="...">
<id ...>
<generator class="org.hibernate.id.TableHiLoGenerator">
<param name="table">...</param>
<param name="column">...</param>
</generator>
</id>
<property name="somethingCommon" />
<joined-subclass name="class_1">
...
...
</joined-subclass>
<joined-subclass name="class_2">
...
...
</joined-subclass>
...
<joined-subclass name="class_n">
...
...
</joined-subclass>
</class>
What I would like to be able to do is put the joined-subclass bits in separate files, just like I would do in code (separate classes -> separate files). Is this possible using just mappings, or perhaps by manipulating the mappings when I load them?
(Note: tagged hibernate/nhibernate, as I don't think this is specific to either flavor)
I believe you can use "extends" eg:
<hibernate-mapping>
<joined-subclass name="DomesticCat" extends="Cat">
...
</joined-subclass>
to separate out the joined subclasses into separate files.