Geeks With Blogs
Mike Nichols - SonOfNun Technology If I were the captain on a big steamboat...
This isn't exactly a "gotcha" since it just has to do with writing mappings correctly and thoughfully. But if you are like me, you use CodeSnippets in VisualStudio 2005 to create all your mappings...the carpal tunnel looming upon me after hand coding a million mapping files (zzzz) forced me into working smarter with Snippets. Anyways, here was my situation. Minor, but took about 15 minutes to debug. Say two classes, class A and Class B, require a many-to-many relationship with each other. Within Nhibernate, one of the classes needs to be in charge of maintaining the relationship. What this means is just that a decision needs to be made on which class Adds/Removes instances from the collection to persist the relationship correctly. On my project, I am using NHibernate.Generics. I decide that Class A should maintain the relationship so in my Class A constructor I have:
_classBs = new EntityList( delegate(ClassB r) { r.ClassAs.Add(this); }, delegate(ClassB r) { r.ClassAs.Add(this); },InitializeOnLazy.Always,OnDuplicate.DoNotAdd);

Now, in my ClassB constructor I have this:
_classAs= new EntityList( delegate(ClassA t) { t.ClassBs.Add(this); }, delegate(ClassA t) { t.ClassBs.Add(this); });
Then, in my Class A mapping I have this:
<bag name="ClassBs" access="NHibernate.Generics.GenericAccessor, NHibernate.Generics" lazy="false" cascade="all" table="ClassB_ClassA" inverse="true"> <key column="ClassAId"/> <many-to-many class="ClassB" column="ClassBId"/> </bag>
Then in my Class B mapping I have:
<bag name="ClassAs" access="NHibernate.Generics.GenericAccessor, NHibernate.Generics" lazy="false" table="ClassB_ClassA" cascade="none"> <key column="ClassBId"/> <many-to-many class="ClassA" column="ClassAId"/> </bag>
In my case, I had forgotten to put the "inverse=true" attribute for the collection of ClassBs in ClassA. This is because I use snippets and more often I am doing one-to-many collections where the "one" maintains the relationship and so I wouldn't have "inverse-true" expressed on the many-side. This was resulting in duplicate records in my join-table (ClassB_ClassA) because NHibernate wasn't sure WHO was maintaining the relationship...that's what the little "inverse" flag helps establish. Posted on Thursday, June 8, 2006 8:42 AM O/R Mappers | Back to top


Comments on this post: NHibernate Gotchas - Many-to-many duplicate records

# re: NHibernate Gotchas - Many-to-many duplicate records
Requesting Gravatar...
Thanks, helpful.
Left by Marvel on Sep 03, 2007 5:34 AM

# re: NHibernate Gotchas - Many-to-many duplicate records
Requesting Gravatar...
You saved my day. This duplicate records problem drove me mad for a few hours. I went through so many posts and finally bumped into yours. I'll remember the inverse="true". Thanks a lot
Left by Rishabh on Apr 21, 2009 11:13 PM

# re: NHibernate Gotchas - Many-to-many duplicate records
Requesting Gravatar...
hi I have 3 tables aspnet_Roles, Permissions and a link table RolePermissions, I have existing data in aspnet_Roles and Permissions table, i wanne add related data to the link table to add a permission to a role, is it possible for me to do it through aspnet_roles mapping?
I tried and it's trying to write to the asp_roles table instead of RolePermission.
e.g

public class aspnet_RolesMapper : ClassMap<aspnet_Roles>
{
public aspnet_RolesMapper()
{
WithTable("aspnet_Roles");
Id(x => x.RoleId).GeneratedBy.Guid();
Map(x => x.RoleName);
Map(x => x.LoweredRoleName);
Map(x => x.Description);
References<aspnet_Application>(x => x.ApplicationId, "ApplicationId");
HasManyToMany<Permission>(x => x.RolePermission)
.WithTableName("RolePermissions")
.WithParentKeyColumn("RoleId")
.WithChildKeyColumn("PermissionID")
.Cascade.All()
.Inverse()
;
}
}
Left by Mardy on Jun 11, 2009 6:04 AM

Your comment:
 (will show your gravatar)


Copyright © Mike Nichols | Powered by: GeeksWithBlogs.net