如何使用NHibernate/FluentNHibernate将三个表中的行映射到一个实体?

如何使用NHibernate/FluentNHibernate将三个表中的行映射到一个实体?,nhibernate,join,fluent-nhibernate,Nhibernate,Join,Fluent Nhibernate,由于我对NHibernate/FluentNHibernate还不熟悉,所以我解决了这个特殊的问题。我将详细描述这个问题,但在此之前,我想提及的是,我可以根据自己的情况自由更改域模型和底层数据库。然而,对于我目前的设计,我有具体的原因,如果可以的话,我会坚持下去 我有一个用户实体。用户有一些偏好,例如他们选择的文化(“en US”/“fr CA”等)和他们首选的转换系统(公制/英制等)。还有其他首选项,随着时间的推移,可以(也将)添加更多首选项。因此,我不希望将首选项表示为基础用户表上的列。相反

由于我对NHibernate/FluentNHibernate还不熟悉,所以我解决了这个特殊的问题。我将详细描述这个问题,但在此之前,我想提及的是,我可以根据自己的情况自由更改域模型和底层数据库。然而,对于我目前的设计,我有具体的原因,如果可以的话,我会坚持下去

我有一个用户实体。用户有一些偏好,例如他们选择的文化(“en US”/“fr CA”等)和他们首选的转换系统(公制/英制等)。还有其他首选项,随着时间的推移,可以(也将)添加更多首选项。因此,我不希望将首选项表示为基础用户表上的列。相反,我希望表结构如下所示(伪SQL):

一个首选项(即“文化”)可以有多个首选项选项(即“en GB”、“fr CA”)。用户的首选项保存在UserPreferences表中,该表具有PreferenceOption表的外键

我希望我的域模型如下所示:

public class User
{
  public virtual Guid {get;set;}
  public virtual Preferences {get;set;}
}

public class Preferences
{
  public virtual CultureInfo Culture{get;}
  public virtual ConversionType ConversionType {get;}
}
我设想我会尝试将属于用户的所有首选项加载到集合中(在preferences类上),并让属性分别转换为CultureInfo和ConversationType(自定义枚举)


我真的很感激你能给我一些建议。

我认为在这种情况下,NHibernate无法处理所有棘手的案件。如果您没有
首选项选项
表中
文化信息
Id
首选项,会发生什么情况?如果
首选项根本不存在怎么办?它如何知道将
CultureInfo
映射到
PreferenceOption
表中的特定行?(
Description
真的是描述要填充哪个属性的常量吗?)

我想你是自找麻烦。如果您想使用这样的模式,我认为您将有更好的运气,将您的模式更直接地映射到您的NHibernate POCO。从与用户相关的
PreferenceOption
表的行中,您可以编写一些代码来填充
首选项
对象

坦率地说,如果您已经知道会有一些用户首选项,请将它们添加到您的模式中。在许多情况下(比如报告,等等——至少少了一个连接,多了一个决定论),处理这个问题要比为基本上没有类型的动态数据创建一个“转储”表容易得多


如果你认为你需要它,我会把垃圾场留在里面,以防万一。但是,如果您在开发过程中的这一点上能够灵活地将您所知道的数据包含在您的模式中,那么就可以这样做。

我认为NHibernate无法处理这种情况下的所有极端情况。如果您没有
首选项选项
表中
文化信息
Id
首选项,会发生什么情况?如果
首选项根本不存在怎么办?它如何知道将
CultureInfo
映射到
PreferenceOption
表中的特定行?(
Description
真的是描述要填充哪个属性的常量吗?)

我想你是自找麻烦。如果您想使用这样的模式,我认为您将有更好的运气,将您的模式更直接地映射到您的NHibernate POCO。从与用户相关的
PreferenceOption
表的行中,您可以编写一些代码来填充
首选项
对象

坦率地说,如果您已经知道会有一些用户首选项,请将它们添加到您的模式中。在许多情况下(比如报告,等等——至少少了一个连接,多了一个决定论),处理这个问题要比为基本上没有类型的动态数据创建一个“转储”表容易得多


如果你认为你需要它,我会把垃圾场留在里面,以防万一。但是,如果您能够灵活地在开发过程中的这一点上将您所知道的数据包含在您的模式中,那么就可以这样做。

谢谢您的回复。其思想是能够在不必更新所有用户行的情况下向系统添加新的首选项-因此,如果用户没有特定的首选项集,则默认值将在域逻辑中处理。此外,首选项的类型对应于一个枚举(PreferenceType),NHibernate可以将该枚举映射到“Description”列并返回。如果我知道描述类型,我可以将首选项的值(从nvarchar)转换为我域中正确的类型,即使用“en GB”作为CultureInfo类的参数。事实上,经过反思,我认为你是对的。我用错误的方式攻击它。底层数据结构很好,但我建模错误。这就是当你盯着同一个问题看几个小时时会发生的事情。你帮我看清了!非常感谢。我接受你的回答。@Øyfind,即使你在.hbm.xml中使用了
语句,你似乎也会面临同样的问题。(顺便说一句,这在您的情况下无论如何都不起作用,因为它是一对多。)也就是说,如果您更新架构为用户首选项添加一个新列,默认情况下它将为NULL,并且您的域逻辑可以通过替换默认值来处理该NULL值。无论如何,如果您必须使用此模式,只需将您的首选项映射到另一个实体,并拥有您的
首选项。让{}
property来做这项繁重的工作。@Øyvind,很高兴我能帮上忙。(很抱歉,如果上面的评论没有意义,我在看到你的第二次回复之前就发布了。)谢谢你的回复。其思想是能够在不必更新所有用户行的情况下向系统添加新的首选项-因此,如果用户没有特定的首选项集,则默认值将在域逻辑中处理。此外,首选项的类型对应于NHi指定的枚举(PreferenceType)
public class User
{
  public virtual Guid {get;set;}
  public virtual Preferences {get;set;}
}

public class Preferences
{
  public virtual CultureInfo Culture{get;}
  public virtual ConversionType ConversionType {get;}
}