使用Fluent NHibernate的一对一关系的正确设计是什么?



我有一张食谱表。每个Recipe在RecipeMetadata表中只有一行,其中包含有关该Recipe的各种数据,由于各种原因,我不想将这些数据存储在Recipes表中。因此,RecipesRecipeMetadata具有一对一的映射。我的Recipes表如下:

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);
}
}

这是我的RecipeMetadata表格:

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();
}
}

但是,当我加载Recipe并访问Metadata属性时,它会尝试在RecipeMetadata中查找Recipes.RecipeId = RecipeMetadata.RecipeMetadataId所在的行。换句话说,它使用两个表上的主键进行联接。

在我的表模式中,RecipeMetadataId是该表唯一的键,与RecipeId无关。RecipeMetadata有另一列,也称为RecipeId,它对`Recipes有外键约束。JOIN的工作方式应该是:

Recipes.RecipeId = RecipeMetadata.RecipeId

我的问题:

  1. 我希望RecipeMetadata有自己的唯一ID,并使用单独的列将其链接到Recipes,这错了吗?显然,我在RecipeMetadata.RecipeId上有一个FK约束和一个唯一索引,所以没有性能影响。是的,磁盘上有一些额外的字节,用于在这个表上存储一个可以说是不必要的ID。

  2. 我从未见过一个表的主键在另一个表上也有外键约束。这种做法合法吗?默认情况下,这似乎是nHibernate更喜欢的行为方式。我应该让步让它顺其自然吗?

  3. 如果我不想更改数据库(尽管如果有正当理由,我可以被说服这样做),我如何用这个模型创建所需的一对一映射?

NHibernate对一对一关系有严格的定义。严格但公平。在NHibernate中,一对一关系意味着表a中的一行在表B中总是有一个匹配的行。

  1. 无论是对是错,NHibernate的一对一映射都不起作用。请注意,您提出的模型与一对多关系的建模方式相同
  2. 它是合法的,并加强了一对一的关系
  3. 由于您希望配方始终有一个关联的元数据行,因此我将使用NHibernate的一对一映射对其进行建模。或者,您可以将其映射为一对多,但只将一个实例作为属性公开

另请参阅:Ayende关于该主题的帖子。

最新更新