6

我有这个实体关系。

public abstract class UserGroup
{
    public virtual int UserGroupId { get; set; }
    public virtual int GroupType { get; set; }
    public virtual string GroupName { get; set; }
    public virtual IList<UserGroupMember> GroupMembers { get; set; }
}

public class UserGroupMember
{
   public virtual int UserGroupMemberId { get; set; }
   public virtual User User { get; set; }
   public virtual UserGroup UserGroup { get; set; }
}

请注意,这UserGroup是基类,并且我有一些派生类被UserGroup.GroupType. 我正在使用Single Table Per Class Hierarchy继承映射策略。

流畅的 NHibernate 映射:

public class UserGroupMap : BaseClassMap<UserGroup>
{
    public UserGroupMap()
    {
        Table("UserGroup");
        Id(x => x.UserGroupId);

        DiscriminateSubClassesOnColumn("GroupType");

        Map(x => x.GroupName);

        HasMany(x => x.GroupMembers)
            .KeyColumn("UserGroupId")
            .Cascade.AllDeleteOrphan()
            .Inverse();
    }
}

public class UserGroupMemberMap: BaseClassMap<UserGroupMember>
{
    public UserGroupMemberMap()
    {
        Table("UserGroupMember");
        Id(x => x.UserGroupMemberId);

        References(x => x.User, "UserId")
            .Cascade.SaveUpdate();

        References(x => x.UserGroup, "UserGroupId")
            .Cascade.SaveUpdate();
    }
}

这就是我想要实现的目标:
我想让 UserGroupMember 也成为一个基类,并让它在鉴别器上进行UserGroup.GroupType区分。这可能吗?

这个问题的另一种表述方式是,如果我可以添加以下行,那就太好了:

DiscriminateSubClassesOnColumn("UserGroup.GroupType");

进入UserGroupMemberMap

4

1 回答 1

6

一、我们不能使用DiscriminateSubClassesOnColumn("UserGroup.GroupType");

在许多其他充分的理由中,discriminator由 NHiberante 管理。这意味着,在任何子对象创建期间,这样的值必须很容易插入。并且不适用于包含的外部表/引用...

二、但在这些情况下,我们可以另辟蹊径。让我们观察文档(在xml映射中,但流利的只是它上面的包装器)

5.1.6。鉴别器

<discriminator
        column="discriminator_column"      (1)
        type="discriminator_type"          (2)
        force="true|false"                 (3)
        insert="true|false"                (4)
        formula="arbitrary SQL expression" (5)
/>

(1) column (可选 - 默认为 class) 鉴别器列的名称。
(2) type (可选 - 默认为 String) 指示 NHibernate 类型的名称
(3) force (可选 - 默认为 false) "force" NHibernate 指定允许的鉴别器值,即使在检索根类的所有实例时也是如此。
(4)如果您的鉴别器列也是映射复合标识符的一部分,则插入(可选 - 默认为 true)将其设置为 false。
(5)公式(可选)当必须计算类型时执行的任意 SQL 表达式。允许基于内容的歧视。

真正对我们非常有趣和有帮助的是(4)(5)。我们可以简单地将鉴别器设置为只读 (不插入)并使用公式

<discriminator insert="false"
 formula="(SELECT ug.GroupType FROM UserGroup ug WHERE ug.UserGroupId = UserGroupId)"/>

注意:最后一个UserGroupId将被 NHibernate 视为当前表中的一列。这是必不可少的和真棒...

好的。现在我们<discriminator>确实返回了正确的值。它也不会在创建新实例期间插入值。我们只需要确定,将分配适当的UserGroup参考,以及所需的类型...

流利应该是显而易见的,但可以肯定的是:

DiscriminateSubClassesOnColumn(null)
    .Formula("(SELECT...")
    .ReadOnly()
    ;
于 2014-10-15T05:50:16.470 回答