views:

133

answers:

1

Using NHibernate, how can I map the following scenario:

public class User
{
    public virtual IDictionary<Project, IList<Role>> ProjectAssignments { get; set; }
}

In the database I have separate tables for User, Project and Role and a fourth table for the relationship.

Any help would be appreciated.

A: 

You can't - from Ayende's blog discussing <map>

I would like to point out that I have still not covered all the options for <map/>, there are even more options (Although, IDictionary<K, IList<V >> is not something that is possible to map, for the problematic SQL statements that would be required to do so).

You'll need some intermediary entity/component. I'd probably have a ProjectAssignment entity to break up the nary association between User, Project and Role - it will probably grow extra attributes as time goes on (say you want to track changes to the assignments over time, so it gets StartDate and EndDate properties).

Something like:

public class User {
  // ... other attributes etc.
  public virtual ISet<ProjectAssignment> Assignments {get;set;}
}

public class Project {
  // ... other attributes etc.
  public virtual ISet<ProjectAssignment> Assignments {get;set;}
}

public class Role {
  // ... other attributes etc.
}

public class ProjectAssignment
{
  public virtual Int64 {get;set;}
  public virtual User User {get;set;}
  public virtual Project Project {get;set;}
  public virtual Role Role {get;set;}
  // ... other attributes etc.
}

I'd just map the ProjectAssignment as a persistent class in its own right, and the User.Assignments collections as a normal one-to-many of whatever flavour. Finally, I'd add a method to extract the details into a dictionary (or probably an ILookup if you're using Framework v3.5): something like:

ILookup<Project, Role> GetRolesByProject() {
    return Assignments.ToLookup(x => x.Project, x => x.Role);
}
Dave W
I am a bit confused about how everything is going to fit. Can you please give me an example of what the intermediary entity is going to look like and how I would map it?
Husain
I've extended my answer now.
Dave W
Thanks a lot for the code :) It worked!
Husain