NHibernate on a too-many-to-many experiment

Warning: this was an inconclusive experiment and I don’t recommend using it at all.

Proceeding with the NHibernate experiments, I’m tried to implement an unusual scenario for a many-to-many relation between different entities and tags. Basically, what I’m trying to accomplish is a way to do a many-to-many mapping between different tables and the tags table using only one junction table between them. Here is a diagram for the idea.

Of course, it will not be possible to add a constraint to the entity_id column other than the primary key, but that’s the idea, make it flexible enough so it can relate to any other table.

The Class Diagram

The class diagram is basically an extension of what I did in the previous post, all I’m adding is the Tag class and one more class for the Color Palettes, just to help demonstrate the scenario.

As illustrated from the class diagram, the Tag class has no reference to the other classes, only the other classes have a collection of tags. That is the main missing point for this experiment. We will see an example of this in a moment.

The Mapping Files

I’m only showing here the mapping for the Template and the Tag classes because the other two are exactly the same as the Template.

As we can see, there is nothing special about the Tag mapping yet, the difference is only for the Template where we map the collection of Tags.

Also, to make it flexible enough to use the same mapping in all the classes, we need to prevent NHibernate from creating the foreign key in the entity_id column. We can achieve this by specifying foreign-key=”none”. The “none” value is magic foreign-key name that will prevent it from being created.

Inserting and Reading Data

And finally, some write and read operations.

object colorPaletteId;
object templateId;

using (var session = NHibernateHelper.CreateSession())
{
    using (var transaction = session.BeginTransaction())
    {
        var tag1 = new Tag("tag1");
        var tag2 = new Tag("tag2");
        var tag3 = new Tag("tag3");

        session.Save(tag1);
        session.Save(tag2);
        session.Save(tag3);

        var colorPalette = new ColorPalette("Black and White");
        colorPalette.Tags.Add(tag1);
        colorPalette.Tags.Add(tag2);
        colorPaletteId = session.Save(colorPalette);

        var template = new Template("Template");
        template.Tags.Add(tag1);
        template.Tags.Add(tag2);
        template.Tags.Add(tag3);
        templateId = session.Save(template);

        transaction.Commit();
    }
}

using (var session = NHibernateHelper.CreateSession())
{
    using (var transaction = session.BeginTransaction())
    {
        var colorPalette = session.Get<ColorPalette>(colorPaletteId);
        Console.WriteLine(
            string.Join(",", colorPalette.Tags.Select(x => x.Name)));

        var template = session.Get<Template>(templateId);
        Console.WriteLine(
            string.Join(",", template.Tags.Select(x => x.Name)));
    }
}

The code work as expected and the output will be:

tag1, tag2
tag1, tag2, tag3

Conclusion

The entire experiment was not a disaster, I believe we were able to accomplish and learn something. What is mostly pending is a way to query all the templates that belong to a given tag, same for the other tables. So, at the end of the day, this solution ends up not being a real many-to-many relation (it is more like a too-many-to-many), because there is currently not a way to map back from the tags to the entities. Therefore, I don’t recommend it, yet. At least, not until I can find a solution.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s