NHibernate Mapping - <dynamic-component/>
Like the <component/> mapping, <dynamic-component/> allows us to treat parts of the entity table in a special way. In this case, it allow us to push properties from the mapping into a dictionary, instead of having to have the entity have properties for it.
This is very useful when we need to build dynamically extended entities, where the client can add columns on the fly.
Let us take this entity as an example:
And this table:
Where we want to have the SSN accessible from our entity, but without modifying its structure. We can do this using <dynamic-component/>:
<class name="Person" table="People"> <id name="Id"> <generator class="identity"/> </id> <property name="Name" /> <dynamic-component name="Attributes"> <property name="SSN" type="System.String"/> </dynamic-component> </class>
And the query just treat this as yet another column in the table:
Comments
That's a great feature, I didn't even know it was there.
So I guess this lets you do:
var person = _session.Load <person(1);
Assert.AreEqual( "123", person.Attributes["SSN"] );
I assume that mapping properties into a dictionary is the primary use case -- very handy for multi-tenanted apps -- are their any other things you've used it for?
Tobin,
Yes, that is what it is for.
It is useful in any case where you need to dynamically extend your entities.
I guess my question would be how do you dynamically extend the entity? Putting some data in the xml document about your mapping doesn't seem very dynamic to me.
Justin,
You usually would do this by manipulating the mapping problematically.
Putting some data in the xml document about your mapping doesn't seem very dynamic to me.
nor does adding a column to the database. Is there anyway you could show an example that uses a property bag in both the database and object model?
Mike, you can create an Attributes table very easily, and map it using standard NH facilities.
That tend to be slower, however, because you need an additional select or a join.
Hrr. I had to use Boo compiler to regenerate entities on-the-fly when adding fields instead of simply using dynamic component..
Thank you for this set of lectures about NHibernate features, Ayende.
Excellent stuff, a question on using an Attributes table comment. How would you make the Attributes property a simple dictionary?
CAM,
Attributes is IDisctionary
Sorry Ayende, I was referring to Mike's comment. Could you show an example of how to map a property bag table (Name/Value Pair) in DB to an IDictionary Attributes property of a class?
CAM,
Take a look at the {map/} element
Excellent Ayende thank you.
How can i solve this (see picture) problem with NHibernate? i have a superclass Question and a lot of subclasses, all with their own specific attributes. I don't want to create table for each class, because of perfomance. The solution is to make an QuestionDetail table with key, value columns where i can store names and values of all specific attributes from subclasses. How can i do it in NHibernate?
tweakers.net/.../full.jpg
Tolly,
Take a look at {map/}
Thanks, Ayende, it works :-)
I have added IDictionary <string,> Properties to my Question class to map key-value pairs. My mapping looks like this:
How can i force NHibernate to use this mapping if I create new QuestionType (subclass) object? Now create a Question object as follows:
<string,> ();
And I'd like to have it so:
Should I use discriminator? Or <subclass? If I use <subclass, than NHibernate just puts subclass attributes to the Question table, or in QuestionType2 table when using <joined-subclass
Thanks in advance :)
Anatoly,
Wait a few days, the post about {join/} will show up
Comment preview