Nhibernate: How to represent Many-To-Many relationships with One-to-Many relationships?

前端 未结 1 438
鱼传尺愫
鱼传尺愫 2020-11-22 16:45

I have read a post on the internet (I can no longer find that post for me to refeence) that a Many-To-Many relationship can be replaced with a one-to-many relationship. Can

相关标签:
1条回答
  • 2020-11-22 17:24

    I just come up to that question, and realized, that there is missing any answer. And it is a shame, while I do often point out this NHibernate documentation statement: 24. Best Practices

    Don't use exotic association mappings.

    Good usecases for a real many-to-many associations are rare. Most of the time you need additional information stored in the "link table". In this case, it is much better to use two one-to-many associations to an intermediate link class. In fact, we think that most associations are one-to-many and many-to-one, you should be careful when using any other association style and ask yourself if it is really neccessary.

    Take a look at the example under the 23.2. Author/Work. Extract, the simplified version of the many-to-many relation between Author and Work:

    <class name="Work" table="works" ...>
            <id name="Id" column="id" generator="native" />
            ...
            <set name="Authors" table="author_work" lazy="true">
                <key>
                    <column name="work_id" not-null="true"/>
                </key>
                <many-to-many class="Author">
                    <column name="author_id" not-null="true"/>
                </many-to-many>
            </set>
    </class>
    

    And its many-to-many target Author:

    <class name="Author" table="authors">
      ...
      <set name="Works" table="author_work" inverse="true" lazy="true">
         <key column="author_id"/>
         <many-to-many class="Work" column="work_id"/>
      </set>
    </class>
    

    So, if we would like to order the set of Works on load, we do have a problem. There is no column in the pair table. But what's more important, there is no way how to manage such a column.

    What we can do, is to introduced the Pair object: AuthorWork and extend the Pair table as needed

    public class AuthorWork
    {
    
        public virtual Author Author { get; set; }
        public virtual Work Work { get; set; }
        public virtual int OrderBy { get; set; }
    }
    

    Mapping of the AuthorWork

    <class name="AuthorWork" table="author_work">
        ...
        <many-to-one name="Author" column="author_id" />
        <many-to-one name="Workr"  column="work_id" />
        <property name="OrderBy" />
    

    Having this we can convert the many-to-many mapping to one-to-many, for example the Authors collection:

    <set name="Authors" lazy="true"
      order-by="OrderBy">
      <key column="work_id" not-null="true"/>
      <one-to-many class="AuthorWork" />
    </set>
    

    And we can manage the entity AuthorWork, set the OrderBy column, and therefore effectively work with the pairing table.

    NOTE: have to agree with that suggestion in docsumentation The more requirements come, the more happy we are that we do have a way how to manage the relation!

    0 讨论(0)
提交回复
热议问题