views:

43

answers:

1

I have a TrackLog that has a collection of TrackPoints:

public class TrackLog
{
    public string Name { get; set; }
    public ISet<TrackPoint> TrackPoints { get; set; }
}

public class TrackPoint
{
    public DateTime Timestamp { get; set; }
    public double Latitude { get; set; }
    public double Longitude { get; set; }
}

I'd like to map the track points as a collection of components, as this makes the most sense. According to the book NHibernate in Action, on page 187:

Collections of components are mapped similarily to other collections of value type instances. The only difference is the use of <composite-element> in place of the familiar <element> tag.

How would I do this using Castle ActiveRecord attributes?

Solution:

To expand on Mauricio's answer, the correct mapping is like so:

[ActiveRecord]
public class TrackLog
{
    [Property]
    public string Name { get; set; }

    [HasMany(DependentObjects = true,
             MapType = typeof(TrackPoint),
             Table = "TrackPoint",
             ColumnKey = "TrackLog_Id"
    )]
    public ISet<TrackPoint> TrackPoints { get; set; }
}

You must provide the MapType, Table, and ColumnKey properties in addition to DependentObjects.

MapType: the type of the class you want to map to

Table: name of the table in the database for the component list

ColumnKey: name of the foreign key column used to relate the child to the parent

Update:

You cannot use Set as the RelationType. It will cause NHibernate to exhibit some weird behavior, where it saves the entities, deletes them, and the re-saves two copies of each element. In the case of my TrackLog, it saved 25 TrackPoints, deleted them, then saved the 25 TrackPoints again two times, for a total of 50. Then when the SessionScope was disposed, it saved another 25, for a total of 75 TrackPoints instead of the expected 25. I couldn't find out the source of this problem, but the fix is to avoid using Set and use Bag (or something else, I only tested it with Bag) instead.

A: 

Use DependentObjects = true, e.g.:

public class TrackLog {
   [Property]
   public string Name { get; set; }

   [HasMany(DependentObjects = true)]
   public ISet<TrackPoint> TrackPoints { get; set; }
}
Mauricio Scheffer
Thanks Mauricio, you're a lifesaver :).
Daniel T.
Are you in charge of the Castle ActiveRecord official documentation at all? I believe this would be good to add to the section on mapping components.
Daniel T.
+1. BTW Anyone can contribute to Castle's documentation. You too Daniel :)
Krzysztof Koźmic