Ayende @ Rahien

Refunds available at head office

NHibernate Mapping -

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:

image

And this table:

image

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:

image

Comments

Tobin Harris
04/11/2009 10:39 AM by
Tobin Harris

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?

Ayende Rahien
04/11/2009 10:45 AM by
Ayende Rahien

Tobin,

Yes, that is what it is for.

It is useful in any case where you need to dynamically extend your entities.

justin
04/11/2009 04:40 PM by
justin

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.

Ayende Rahien
04/11/2009 06:06 PM by
Ayende Rahien

Justin,

You usually would do this by manipulating the mapping problematically.

Mike
04/12/2009 02:16 AM by
Mike

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?

Ayende Rahien
04/12/2009 02:58 AM by
Ayende Rahien

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.

meowth
04/13/2009 07:12 AM by
meowth

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.

CAM
04/15/2009 11:39 AM by
CAM

Excellent stuff, a question on using an Attributes table comment. How would you make the Attributes property a simple dictionary?

Ayende Rahien
04/15/2009 11:41 AM by
Ayende Rahien

CAM,

Attributes is IDisctionary

CAM
04/15/2009 12:57 PM by
CAM

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?

Ayende Rahien
04/15/2009 01:28 PM by
Ayende Rahien

CAM,

Take a look at the {map/} element

CAM
04/15/2009 01:51 PM by
CAM

Excellent Ayende thank you.

tolly
04/15/2009 03:43 PM by
tolly

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

Ayende Rahien
04/15/2009 07:50 PM by
Ayende Rahien

Tolly,

Take a look at {map/}

tolly
04/16/2009 08:13 AM by
tolly

Thanks, Ayende, it works :-)

I have added IDictionary <string,> Properties to my Question class to map key-value pairs. My mapping looks like this:

{map name="Properties" table="QuestionDetails" }

  {key column="QuestionID" /}

  {index column="Name" type="String" /}

  {element column="Value" type="String" /}

{/map}

How can i force NHibernate to use this mapping if I create new QuestionType (subclass) object? Now create a Question object as follows:

        Question sbq = new Question();

        sbq.attr1= "attr1value";

        sbq.attr2= "attr2value";

        sbq.Properties = new Dictionary

<string,> ();

        sbq.Properties.Add( "attr3", "attr3" );

        sbq.Properties.Add( "attr4", "attr4" );

And I'd like to have it so:

        QuestionType2 sbq = new QuestionType2 ();

        sbq.attr1= "attr1value";

        sbq.attr2= "attr2value";

        sbq.attr2= "attr3value";

        sbq.attr2= "attr4value";

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 :)

Ayende Rahien
04/16/2009 08:20 AM by
Ayende Rahien

Anatoly,

Wait a few days, the post about {join/} will show up

Comments have been closed on this topic.