NHibernate - 我有很多,但我只想要一个!

时间:2010-04-09 02:35:44

标签: sql nhibernate view formula one-to-one

我有一个可以拥有许多电子邮件的用户。这是通过List集合映射的(由用户上的IEnumerable电子邮件公开)。 对于每个用户,其中一个电子邮件将是主要电子邮件(电子邮件中的“布尔IsPrimary”属性)。

如果没有NHibernate加载用户的每封电子邮件,如何从用户获取主要电子邮件?

我有以下两个实体,每个

都有一个对应的表
public class User
{
   private readonly IList<Email> _emails;

   public virtual int Id { get; private set; }
   public virtual IEnumerable<Email> Emails { get { return _emails; } }
   // public virtual Email PrimaryEmail { get; set; } - Possible somehow ?
}
public class Email
{
   public virtual int Id { get; private set; }
   public virtual String Address { get; set; }
   public virtual Boolean IsPrimary { get; set; }
   public virtual User User { get; set; }
}

我可以将用户的“电子邮件PrimaryEmail”属性等映射到以某种方式设置“IsPrimary = 1”的电子邮件吗? 也许使用Sql公式?一个看法 ?一对一的关系?或者其他方式?

应该可以将主电子邮件更改为其他电子邮件之一,因此我希望将它们全部保存在1个表中,只需更改IsPrimary属性即可。

使用Sql公式,如果我将当前主电子邮件上的IsPrimary属性设置为false,然后将PrimaryEmail属性设置为false,是否可以使用户的“PrimaryEmail”属性保持最新状态电子邮件应该是新的主电子邮件并将IsPrimary设置为true? NHibernate会跟踪Sql公式加载的“旧/当前”主要电子邮件的变化吗? 使用SqlFormula时,1级缓存和2级缓存怎么样?

我不知道它是否可以使用View?然后我猜电子邮件可以像组件一样映射?从View中加载时更新电子邮件数据是否有效?

有更好的方法吗?

由于我在用户和电子邮件之间存在双向关系,我当然可以在许多情况下查询主电子邮件,然后使用电子邮件中的“用户”属性来获取用户(而不是相反的方式)从用户到主要电子邮件)

希望有人可以提供帮助吗?

2 个答案:

答案 0 :(得分:1)

乍一看,我想我想确保PrimaryEMail始终是对集合中某个EMail对象的引用(这样做的一种方法是让get / set完全处于运行状态)。使用像您一样的全公共设计,您必须将更改与EMail和/或集合上的事件处理程序挂钩。新的主要电子邮件对象(您要提升为主要内容的集合中的某些内容)将了解其父集合或用户,因此应该能够找到当前主要对象以使其成为辅助。

备选方案包括使IsPrimary不是公共集,甚至不公开公开(email.IsPrimary将替换为email == user.PrimaryEMail)。 PrimaryEMail set方法可能只接受集合中已有的EMail对象。

我只是在手动ORM类中完成了这个,并且找不到在NHibernate中执行这个相当常见的场景的规范方法。必须有一个。

答案 1 :(得分:1)

首先。你为什么在那里使用IEnumerable?是否要在每次访问该属性时启动查询?为什么它有公共制定者?

对我来说,你希望它是IList或ICollection。有一个列表会更有意义,因为我会添加两个方法:

User.SetPrimary(int index)
User.GetPrimary()
User.ICollection Emails { get; protected set; }

Email.IsPrimary { get; protected set; }

首先通过电子邮件进行迭代,以确保只有一个项目设置为主要邮件,第二个项目通过电子邮件进行迭代,直到找到一个被标记为主要邮件的项目。