nhibernate saving a dictionary in a ternary relation
Class:
class Track
{
...
public virtual IDictionary<People, Role> PeopleRoles { get; set; }
}
Mapping:
<class name="Track" ...>
...
<map name="PeopleRoles" table="track_people_role">
<key column="track_id"/>
<map-key-many-to-many column="people_id" class="People"/>
<many-to-many colum开发者_StackOverflow社区n="role_id" class="Role"/>
</map>
</class>
When I execute the code below I can see the row inserted in track_people_role table as 47637,10,1
Person p = PersonManager.GetById(10);
Role pr = RoleManager.GetById(1);
Track t = TrackManager.GetById(47637);
t.PeopleRoles.Add(p, pr);
TrackManager.Save(t);
after when I execute the previous with a different role I get "An item with the same key has already been added" error
Person p = PersonManager.GetById(10);
Role pr = RoleManager.GetById(2);
Track t = TrackManager.GetById(47637);
t.PeopleRoles.Add(p, pr);
TrackManager.Save(t);
Any ideas how i can manage to insert the second row.
EDIT:
Mapping:<class name="TrackPersonRole, App.Data" table="trackpeoplerole" lazy="true">
<composite-id>
<key-many-to-one name="Person" class="Person" column="people_id"/>
<key-many-to-one name="Role" class="Role" column="role_id"/>
</composite-id>
</class>
<class name="Track" ...>
...
<bag name="TrackPeopleRoles">
<key column="track_id"/>
<one-to-many class="TrackPersonRole"/>
</bag>
</class>
TrackPersonRole tpr = new TrackPersonRole();
tpr.Person = PersonManager.GetById(10);
tpr.Role = RoleManager.GetById(2);
entity.PeopleRoles.Add(tpr);
TrackManager.SaveOrUpdate(entity);
generates the below update statement, instead of an insert.
UPDATE trackpeoplerole SET track_id = 47637 /* ?p0 */
WHERE people_id = 10 /* ?p1 */ AND role_id = 2 /* ?p2 */
The error message is correct: you are adding a duplicate key to a dictionary.
It does not even come from NHibernate - it's generated by the Dictionary
class.
If a Track
can have the same Person
in more than one Role
, you'll have to map the track_person_role
table as an entity:
class Track
{
...
public virtual ICollection<TrackPersonRole> PeopleRoles { get; set; }
}
class TrackPeopleRole
{
public virtual Person Person { get; set; }
public virtual Role Role { get; set; }
}
Mapping:
<class name="Track" ...>
...
<bag name="TrackPeopleRoles">
<key column="track_id"/>
<one-to-many class="TrackPersonRole"/>
</map>
</class>
There are more details regarding inverse
and cascade
, but start with this.
精彩评论