简体   繁体   中英

What's the proper design for a one-to-one relationship using Fluent NHibernate?

I have a table of Recipes. Each Recipe has one and only one row in table RecipeMetadata, which contains various data about the recipe that I don't want to store in the Recipes table for various reasons. Thus, Recipes and RecipeMetadata have a one-to-one mapping. My Recipes table is as follows:

public partial class RecipesMap : ClassMap<Recipes>
{
   public RecipesMap()
   {
      Id(x => x.RecipeId);

      // Map() various columns here

      HasMany(x => x.Ingredients).KeyColumn("RecipeId");
      HasOne(x => x.Metadata);
   }
}

And here's my RecipeMetadata table:

public partial class RecipeMetadataMap : ClassMap<RecipeMetadata>
{
   public RecipeMetadataMap()
   {
      Id(x => x.RecipeMetadataId);

      // Map() various columns here

      References<Recipes>(x => x.Recipe).Column("RecipeId").Not.Nullable();
   }
}

However, when I load a Recipe and access the Metadata property, it attempts to find a row in RecipeMetadata where Recipes.RecipeId = RecipeMetadata.RecipeMetadataId . In other words, it does the join using the primary keys on both tables.

With my table schema, RecipeMetadataId is a key unique only to that table, and has nothing to do with RecipeId . RecipeMetadata has another column, also called RecipeId which has a foreign key constraint on `Recipes. The JOIN should work as:

Recipes.RecipeId = RecipeMetadata.RecipeId

My Questions:

  1. Am I wrong for wanting RecipeMetadata to have its own unique ID, and to use a separate column to link this to Recipes ? Obviously, I have a FK constraint as well as a unique index on RecipeMetadata.RecipeId so there's no perf impact. Yes, there's some extra bytes on the disk for storing an arguably unnecessary ID on this table.

  2. I've never seen a table whose primary key also has a foreign key constraint on another table. Is this legit practice? It seems to be the way nHibernate prefers to behave by default. Should I give in and let it have its way?

  3. Provided I don't want to change the database (Though I can be convinced to do so if given a legitimate reason), how can I create the desired one-to-one mapping with this model?

NHibernate has a strict definition of one-to-one relationships. Strict but fair. In NHibernate one-to-one relationship means that the a row in table A always has a matching row in table B.

  1. Right or wrong, that won't work with NHibernate's one-to-one mapping. Note that the model you propose is identical to how a one-to-many relationship would be modeled.
  2. It's legit and enforces the one-to-one relationship.
  3. Since you want the recipe to always have an associated metadata row, I would model it using NHibernate's one-to-one mapping. Alternatively, you can map it as one-to-many but only expose one instance as a property.

See also: Ayende's post on the topic .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM