Many to Many by convention

50 views
Skip to first unread message

Riderman Sousa

unread,
May 22, 2013, 9:37:56 AM5/22/13
to Fluent NHibernate Group
How to do In many to many relationship, where no child class.
How to generate a table by convention linking the two?

Tables to be generate:
table Person
  Id
  Name

table Company
  Id
  Name

table PersonCompany
  PersonId
  CompanyId

Current class
class Person
  string Name
  
class Company
  string Name
  IList<Person> Persons

As you can see, there are no IList<Company> child property on class Person.
How to generate a second table (PersonCompany) by convention in this case?

Riderman de Sousa Barbosa

Web Developer | MCPD Certify

Skype.: 4042-6002 | Cel.: (31) 8681-1986

bindsolution.com

Microsoft Parner Network


Carl Bussema

unread,
May 22, 2013, 9:51:24 AM5/22/13
to fluent-n...@googlegroups.com
I don't think you can. You either need a bidirectional association or a classmap or an override. I wouldn't want to have a convention deciding which relationships were 1:N and which where N:M... you can read it from the Domain model or you can spell it out if you're not using bidirectional associations. You can write an override mapping that just spells out the mapping details you can't get from convention, or where you want to change the convention.

I could be wrong about whether it's possible, but you have to ask at what point you're relying too much on conventions.


--
You received this message because you are subscribed to the Google Groups "Fluent NHibernate" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fluent-nhibern...@googlegroups.com.
To post to this group, send email to fluent-n...@googlegroups.com.
Visit this group at http://groups.google.com/group/fluent-nhibernate?hl=en-US.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Riderman Sousa

unread,
May 22, 2013, 11:54:36 AM5/22/13
to Fluent NHibernate Group
And if I use some attribute to map this kind of relationship?

like:
class Company
  string Name
  [ManyToMany(TableName="PersonCompany"])
  IList<Person> Persons

I see it in this post, but I failed to implement.

I need a way (convention or not) to perform this task.


Carl Bussema

unread,
May 22, 2013, 12:08:55 PM5/22/13
to fluent-n...@googlegroups.com
That post looks complicated, and I'm still not convinced it's a good idea, but if you can't get it working, use a simpler method.

Define an override class:

public class CompanyMapOverrides : IAutoMappingOverride<Company>
{
public void Override(FluentNHibernate.Automapping.AutoMapping<Company> mapping)
{
mapping.HasManyToMany(a => a.Person).Cascade.AllDeleteOrphan().Not.Inverse();
}

}

Make sure you include the override in your mapping:
 mappings.UseOverridesFromAssemblyOf<CompanyMapOverride>();


Alter Cascade requirements to suit. You can get conventions to declare the table name:

using FluentNHibernate.Conventions.Inspections;
using inflector_extension;
using FNH = FluentNHibernate;


    public class ManyToManyTableNameConvention : FNH.Conventions.ManyToManyTableNameConvention
    {
        protected override string GetBiDirectionalTableName(IManyToManyCollectionInspector collection,
            IManyToManyCollectionInspector otherSide)
        {

            return collection.EntityType.Name.InflectTo().Pluralized + "_" +
                otherSide.EntityType.Name.InflectTo().Pluralized;
        }

        protected override string GetUniDirectionalTableName(IManyToManyCollectionInspector collection)
        {
            return collection.EntityType.Name.InflectTo().Pluralized + "_" +
                collection.ChildType.Name.InflectTo().Pluralized;
        }
    }


Riderman Sousa

unread,
May 22, 2013, 12:49:36 PM5/22/13
to Fluent NHibernate Group
When I do this, I get the following error:

`There is already an object named 'Company' in the database. ---> System.Data.SqlClient.SqlException: There is already an object named 'Company' in the database.`


If not using IAutoMappingOverride what do you recommend?
Create an IList in Person? Like  `IList<Company> Companies`

Carl Bussema

unread,
May 22, 2013, 1:17:52 PM5/22/13
to fluent-n...@googlegroups.com

Yes, but you'll still need to use a map to mark one end inverse. I don't recall how nh operates without that detail. Also use iset or Icollection unless you need to maintain order (1 st 2 nd etc)

Riderman Sousa

unread,
May 22, 2013, 1:23:27 PM5/22/13
to Fluent NHibernate Group

I'll stick with the IAutoMappingOverride :)

Any tips on this error? Only occurs if I set the interface IAutoMappingOverride

public class CompanyConvention : IAutoMappingOverride<Company>
{
    public void Override(AutoMapping<Company> mapping)
    {
        mapping.HasManyToMany(a => a.Persons).Cascade.AllDeleteOrphan().Not.Inverse();
    }
}


Carl Bussema

unread,
May 22, 2013, 1:30:23 PM5/22/13
to fluent-n...@googlegroups.com
Post your entire mapping assembly setup with conventions somewhere, maybe upload a .zip to dropbox or send your code to github and I'll take a look when I have time.

Carl Bussema

unread,
May 22, 2013, 1:30:35 PM5/22/13
to fluent-n...@googlegroups.com

Riderman Sousa

unread,
May 22, 2013, 2:05:01 PM5/22/13
to fluent-n...@googlegroups.com
I found another approach. A little easier than the first,


public class ManyToManyConvention : IHasManyToManyConvention  
{  
    public void Apply(IManyToManyCollectionInstance instance)  
    {  
        if (instance.OtherSide == null)  
        {  
            instance.Table(  
                string.Format(  
                    "{0}To{1}",  
                    Inflector.Pluralize(instance.EntityType.Name),  
                    Inflector.Pluralize(instance.ChildType.Name)));  
        }  
        else  
        {  
            instance.Inverse();  
        }  
    }  
}  
Reply all
Reply to author
Forward
0 new messages