RoryB
RoryB

Reputation: 1047

Mapping a List of ints to an nHibernate entity

So, I have an NHibernate entity which has an associated list, like so:

public class CountSet{

    //Some other code here

    private readonly IList<int> _instanceCounts;

    public virtual IEnumerable<int> InstanceCounts
    {
        get { return _instanceCounts; }
        set
        {
            _instanceCounts.Clear();
            foreach (var instanceCount in value.Distinct())
            {
                _instanceCounts.Add(instanceCount);
            }
        }
    }  
}

And am mapping the entity with Fluent NHibernate, using automapping, but with an override to map the list, like so:

mapping.HasMany(x => x.InstanceCounts) 
            .Table(@"CountSetsInstanceCounts")
            .KeyColumn(@"InstanceCountSetId")
            .Element(@"InstanceCount");

This seems to be correctly creating the hbm xml, which looks like this:

<bag table="CountSetsInstanceCounts" name="InstanceCounts" 
   access="field.camelcase-underscore" inverse="true" 
   cascade="all-delete-orphan">
    <key>
        <column name="InstanceCountSetId"/>
    </key>
    <element type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, ">
        <column name="InstanceCount"/>
    </element>
</bag>

Which looks correct to me. However, when I try and persist these entities to the database, the entity is saved correctly, but the collections are not.

Any suggestions as to what might be happening? Feel free to ask for more information.

Upvotes: 4

Views: 1791

Answers (2)

Radim K&#246;hler
Radim K&#246;hler

Reputation: 123861

You are almost there. Your mapping is correct, and C# entities as well. The point is, that int cannot be managed via "inverse" setting, because it is not an entity. It must be set to inverse="false".

Adjust your mapping this way:

mapping.HasMany(x => x.InstanceCounts) 
   .Table(@"CountSetsInstanceCounts")
   .KeyColumn(@"InstanceCountSetId")
   .Element(@"InstanceCount")
   .Not.Inverse()
;

Upvotes: 2

MichaC
MichaC

Reputation: 13380

This is basically because of your custom setter which uses a backing field. Therefore nhibernate does not have a reference object to track changes against.

You have some options to fix it

a) Remove the custom logic and simply use

public virtual IEnumerable<int> InstanceCounts
{
    get;
    set;
}

This should work with your current mapping because nh can track changes of the auto property.

b) Change your mapping to specify the Access: .Access.CamelCaseField() To make this working, you also have to change the name of your backing field to not start with underscore.

As a side note: You defined the backing field as read-only. This doesn't really make sense if you expose the setter of your property.

If you want to have read-only property, remove the setter and maybe implement a method to set the list of values. Or, if you don't need the read-only flag and still want to have the backing field, change your code to

public virtual IEnumerable<int> InstanceCounts
{
    get { return instanceCounts; }
    set { instanceCounts = value.ToList(); }
}

Upvotes: 0

Related Questions