2

I have recently inherited a project at work that contains NHibernate. I am extremely new to it and have to make a modification to one of the mappings. I've read through the documentation here and I'm still not sure how to do this or if my understanding/terminology is even correct.

So given the following table structure I need a bag that will get me the ProjectName:

User
  UserID (PK)

ProjectUser
  UserID (PK, FK User.UserID)
  ProjectID (PK, FK Project.ProjectID)

Project
  ProjectID (PK)
  ProjectName

Here is the existing bag mapping and it correctly returns the ProjectID, but now I'm trying to understand how I need to modify it to return both the ProjectID and the ProjectName:

<bag name="Projects" table="ProjectUser" lazy="true" inverse="true" cascade="save-update">
  <key column="UserId"></key>
  <many-to-many class="Project" column="ProjectID"></many-to-many>
</bag>
akousmata
  • 1,005
  • 14
  • 34
  • When you say "I need to modify it to return both the ProjectID and ProjectName" what do you mean exactly? If you are wanting to look at all the ProjectNames that belong to a particular User you would just iterate through the collection of Projects for that user and use Project.ProjectName. Generally your relationships above would be represented by 2 classes User and Project. User has a collection of Projects and Projects have a collection of Users. The intermediate table ProjectUsers in your example would not have a C# class mapped to it. – Cole W Apr 17 '14 at 01:47
  • Yes, you are correct, please see my comment in the answer below. This was a project that basically got thrown at me at work because no one else had MVC experience and I have ZERO NHibernate experience so it was mostly just a misunderstanding of how the many-to-many relationships worked. – akousmata Apr 17 '14 at 12:18

1 Answers1

2

Well, your mapping seems to be correct, i.e. already returning the ProjectName. To be sure please, check that the object Project is mapped like this:

<class name="Project" table="Project">
  <id name="Id" column="ProjectID" generator class="native"/> 

  <!-- above as the Id we have mapping for column ProjectId
        below the C# Name will contain the column ProjectName -->

  <property name="Name" column="ProjectName" />

  <!-- related Users to this Project -->
  <bag name="Users" table="ProjectUser" lazy="true" >
    <key column="ProjectID"></key>
    <many-to-many class="User" column="UserID" />
  </bag>

</class>

And the Project would be like this

public class Project 
{
    public virtual int Id { get; set;}
    public virtual string Name { get; set;}
    public virtual IList<User> Users { get; set;}
    ...

So, having this in place, we should be able to use the User:

public class User 
{
    public virtual IList<Project> Projects { get; set;}
    ...

mapped and loaded by NHibernate like this

user = session.Get<User>(x) // id of searched user

foreach(var project in user.Projects)
{
  var name = project.Name;
  var id = project.Id;
  ...
}

NOTES:

In case of many-to-many there obviously could/should be <bag> mapping on both sides - Project and User. But only one of them can have inverse="true". So in this case Project.Users does not have that.

The cascade setting on many-to-many is doing (most likely) different thing than one would expect. It is not related to the pairing table but to the second end of that mapping.

Cascading of the pairing object is done out of the box. It does not have to be mapped, in fact it cannot be mapped or turned off... Other words I would suggest to remove that cascade, unless you really want to change the Project in persistence, if you are working with some User.

Check also:

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • Turns out the mapping from Project back to User was present, but it was commented out and I'm not familiar enough with NHibernate yet to understand why that matters. Uncommenting that fixed it, but that brings up the question of why it was commented and why the User bag wasn't changed after commenting. `"In case of many-to-many there obviously could/should be mapping on both sides"` Not so obvious to a complete noob. And if I'm being honest the documentation is a bit overwhelming but I will look into reworking this as many-to-ones as your links suggest ty! – akousmata Apr 17 '14 at 12:15
  • I know about NHibernate weak side. And the bad news is, that it won't be better, no new development can be seen at all... But yes, please, try to go through existing documentation... and if lost, do not hesitate to place a question here. We, how are surviving aside with NHibernate, will try to help you ;) ;) – Radim Köhler Apr 17 '14 at 12:18