HasMany - Breaking change in 1.1?

Rob Ashton's Avatar

Rob Ashton

25 May, 2010 11:57 AM via web

I've just upgraded to 1.1 and I notice that our build is now failing along with our tests for building and populating the database.

We have a few places in our persistence layer where we choose to only map one side of a One to Many relationship because it keeps our code simple, and our children do not need to know about their parents.

We did this with the following line:

HasMany(x => x.Elements).NotFound.Exception().Cascade.All();

And this would generate the following table structure:

+---------------------------+--------------+------+-----+---------+----------------+
| Field                     | Type         | Null | Key | Default | Extra          |
+---------------------------+--------------+------+-----+---------+----------------+
| VacancyFrameworkElementId | int(11)      | NO   | PRI | NULL    | auto_increment |
| ElementType               | varchar(255) | NO   |     | NULL    |                |
| IsMandatory               | tinyint(1)   | NO   |     | NULL    |                |
| Type                      | int(11)      | NO   | MUL | NULL    |                |
| Source                    | int(11)      | YES  | MUL | NULL    |                |
| MaxLength                 | int(11)      | YES  |     | NULL    |                |
| VacancyFramework_id       | int(11)      | YES  | MUL | NULL    |                |
+---------------------------+--------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)`

However, since upgrading to 1.1, this gives us a structure that looks like this:

+---------------------------+--------------+------+-----+---------+----------------+
| Field                     | Type         | Null | Key | Default | Extra          |
+---------------------------+--------------+------+-----+---------+----------------+
| VacancyFrameworkElementId | int(11)      | NO   | PRI | NULL    | auto_increment |
| ElementType               | varchar(255) | NO   |     | NULL    |                |
| IsMandatory               | tinyint(1)   | NO   |     | NULL    |                |
| Type                      | int(11)      | NO   | MUL | NULL    |                |
| MaxLength                 | int(11)      | YES  |     | NULL    |                |
| Source                    | int(11)      | YES  | MUL | NULL    |                |
| VacancyFramework          | int(11)      | NO   | MUL | NULL    |                |
+---------------------------+--------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)`

Note: The VacancyFramework is now no longer nullable (I have no idea why the name has changed - we have a convention for References and ManyToMany which does this, but not OneToMany - that aside...

The curious thing is, if I change the mapping (in 1.1) to

HasMany(x => x.Elements).NotFound.Exception().Cascade.All().KeyColumn("VacancyFramework")

The column becomes nullable again (my desired outcome)

+---------------------------+--------------+------+-----+---------+----------------+
| Field                     | Type         | Null | Key | Default | Extra          |
+---------------------------+--------------+------+-----+---------+----------------+
| VacancyFrameworkElementId | int(11)      | NO   | PRI | NULL    | auto_increment |
| ElementType               | varchar(255) | NO   |     | NULL    |                |
| IsMandatory               | tinyint(1)   | NO   |     | NULL    |                |
| Type                      | int(11)      | NO   | MUL | NULL    |                |
| MaxLength                 | int(11)      | YES  |     | NULL    |                |
| Source                    | int(11)      | YES  | MUL | NULL    |                |
| VacancyFramework          | int(11)      | YES  | MUL | NULL    |                |
+---------------------------+--------------+------+-----+---------+----------------+

7 rows in set (0.00 sec)1

So what's up? Have I got a convention gone awry somewhere? Has something changed? Do I need to do something additional to my mappings to get a nullable field created in the child table?

Ta,

Rob

  1. 2 Posted by Rob Ashton on 25 May, 2010 12:05 PM

    Rob Ashton's Avatar

    Funnily enough, adding a convention to set the name of the key in a OneToMany relatuionship also has the same effect (making the column nullable)

    public class OneToManyConvention : IHasManyConvention
    {
        public void Apply(FluentNHibernate.Conventions.Instances.IOneToManyCollectionInstance instance)
        {
            instance.Key.Column(instance.EntityType.Name);
        }
    }
    
  2. Support Staff 3 Posted by Paul Batum on 05 Jun, 2010 10:05 AM

    Paul Batum's Avatar

    I'm not sure why this behavior changed, but there is a KeyNullable() method.
    Can't you use that to get your desired outcome?

  3. 4 Posted by Rob Ashton on 06 Jun, 2010 01:25 PM

    Rob Ashton's Avatar

    I couldn't find that for some reason when I was playing around with this,

    Of course, this doesn't explain why setting the name of the key would alter whether it was nullable or not :)

  4. 5 Posted by Rob Ashton on 06 Jun, 2010 01:27 PM

    Rob Ashton's Avatar

    Also, I can't find a way of doing this through convention - obviously I want all of my keys to be nullable, like they were in 1.0!

  5. 6 Posted by Facundo Fumaneri on 02 Jul, 2010 12:20 AM

    Facundo Fumaneri's Avatar

    This error happens when the column name is the begining of table name. In this case, "VacancyFramework" is the column name and "VacancyFrameworkElement" the table name. I don't know the reason. I changed the KeyColumn and it works..

Reply to this discussion

Preview Comments are parsed with Markdown. Help with syntax

Attached Files

    You can attach files up to 10MB

    Ten divided by two is what?