Mapping to multiple tables with Fluent nHibernate

2019-02-13 05:28发布

问题:

Here's my situation..
Suppose you have the following model entities, which represent single tables on their own:

Movies [ Movie_Id, Title, Rating, .. ]
Actors [ Actor_Id, FirstName, LastName, .. ]
Director [ Director_Id, FirstName, LastName, .. ]

And another entity/table called "Recommendations", which represents recommendations between users within a website. The idea is that a recommendation could be of any type, i.e. someone recommending an actor, or someone recommending a movie. Basically, the table should look something like this:

Recommendations [ Recommendation_Id, Object_Id, Object_Type, .. ]

And here's what i'm stuck into. How can I map these relationships in nHibernate with Fluent? I mean.. while mapping, I can't specify the Type (which table related to) 'cause that's determined on runtime, but I can't rely only on the Id 'cause by itself it cannot imply to which table belongs to.
For instance, imagine this record on Recommendations table:

Recommendation_Id--Object_Id--Object_Type
83001--4010123---"M"

Basically I'm storing a char identifier (in this case "M" stands for table "Movies") to know to which table Object_Id belongs to. I cannot just store Object_Id without Object_Type..

As final comments, I'd like to add that I've seen all the table-per-class, table-per-subclass, table-per-concrete-class examples, but I believe none of these fits in this situation, as Movies_Id, Actors_Id, Directors_Id, ... are all different between them, so is Recommendations_Id. I mean, there's no base class-child class inheritance here, they don't share Id's at all..

I hope I make myself clear. Thanks in advance.

回答1:

The NHibernate mapping you are looking for is <any/>. Here are a few resources to help you get up to speed with this NHibernate mapping feature:

  • Ayende's blog post
  • NHibernate documentation
  • Fluent NHibernate documentation

I believe the *.hbm.xml that you are shooting for is something like this:

<class name="Recommendation" table="Recommendations">
  <id name="Id">
    <column name="Recommendation_Id" />
    <generator class="native"/>
  </id>

  <any name="RecommendedObject" id-type="System.Int32" meta-type="System.String">
    <meta-value value="M" class="Movie"/>
    <meta-value value="A" class="Actor"/>
    <meta-value value="D" class="Director"/>
    <column name="Object_Type"/>
    <column name="Object_Id"/>
  </any>

  <!-- other stuff ... -->
</class>

You should be able to accomplish that with Fluent NHibernate like so in Recommendation's mapping:

ReferencesAny(x => x.RecommendedObject)
    .IdentityType<int>()
    .EntityTypeColumn("Object_Type")
    .EntityIdentifierColumn("Object_Id")
    .AddMetaValue<Movie>("M")
    .AddMetaValue<Actor>("A")
    .AddMetaValue<Director>("D");