【问题标题】:NHibernate - mapping many-to-one and many-to-many lookup table relationships without using a second classNHibernate - 在不使用第二类的情况下映射多对一和多对多查找表关系
【发布时间】:2013-11-12 16:41:40
【问题描述】:

我正在映射的数据库包含计划实体。每个计划实体都有一个主要部门(多对一关系)和一组可能的附加部门(多对多关系)。部门存储在只有“ID”和“NAME”列的查找表中。 'PLAN' 表有一个 'DEPARTMENT_ID' 外键列,它存储来自 'DEPARTMENT' 表的 id 以引用主要部门。计划与其他部门之间的关系存储在交叉引用表中,该表具有以下列:“PLAN_ID”和“DEPARTMENT_ID”。

现在,我已经使用 Plan 类和 Department 类成功地映射了这个结构:

public class Plan
{
    public virtual int Id { get; set; }

    public virtual Department ExecutorDepartment { get; set; }

    public virtual IList<Department> AdditionalExecutorDepartments { get; set; }
}

public class Department
{
    public virtual int Id { get; set; }

    public virtual string Name { get; set; }
}

<class name="Plan" table="PLAN">
  <id name="Id" unsaved-value="0">
    <column name="ID" not-null="true" />
    <generator class="native"/>
  </id>
  <many-to-one name="ExecutorDepartment" class="Department" column="DEPARTMENT_ID"/>
  <bag name="AdditionalExecutorDepartments" table="PLAN_DEPARTMENT">
    <key column="PLAN_ID" />
    <many-to-many class="Department" column="DEPARTMENT_ID"></many-to-many>
  </bag>
</class>
<class name="Department" table="DEPARTMENT">
  <id name="Id" unsaved-value="0">
    <column name="ID" not-null="true" />
    <generator class="native"/>
  </id>
  <property name="Name" column="NAME" type="string"/>
</class>

但是,我正在寻找一种方法来删除 Department 类(就应用程序逻辑而言,这完全没用),并让 Plan 类将部门名称存储为字符串,如下所示:

public class Plan
{
    public virtual int Id { get; set; }

    public virtual string ExecutorDepartment { get; set; }

    public virtual IList<string> AdditionalExecutorDepartments { get; set; }
}

有什么办法吗?顺便提一下,我不会更新数据库中的数据,也无法更改数据库结构。

附:我尝试使用&lt;Join&gt; 元素来获取主部门,但显然它只能加入主键(参见https://nhibernate.jira.com/browse/NH-1452)。

【问题讨论】:

    标签: c# nhibernate orm mapping nhibernate-mapping


    【解决方案1】:

    Department 类很可能并非完全没用。下面的代码是什么意思?

    plan.ExecutorDepartment = "Hyoomun Reesorsis";
    plan.ExecutorDepartment = "Human Resources";
    

    您无法判断我们是在修正拼写还是将其分配给不同的部门。

    部门名称是否可以更改?如果是这样,该更改是否需要反映在属于该部门的所有计划中?如果是这样的话,那么从领域驱动设计的角度来看,部门是一个实体,而不是一个价值对象。如果它是一个实体,那么您应该继续使用many-to-onemany-to-many 映射这些关系。这使您的代码更具描述性。要修正拼写,你说...

    plan.ExecutorDepartment.Name = "Human Resources";
    

    ...或者将计划分配给一个新部门,你说:

    plan.ExecutorDepartment = theOtherHrDepartmentThatActuallyCaresAboutSpelling;
    

    这个版本的代码更清楚地说明了它要做什么。

    NHibernate 是一个允许您以面向对象、领域驱动的方式使用关系数据库的工具。当您尝试遵循 DDD 规则时,它的效果最好。从 DDD 的角度来看,您要求做的事情没有意义,因为部门确实有身份,所以 NHibernate 不支持假装它没有身份。您想要做什么没有映射。如果您需要以这种方式建模,您有几个选择。

    A.添加属性以进行挖掘并为您获取字符串。

    public virtual string ExecutorDepartmentName
    {
        get { return ExecutorDepartment != null ? ExecutorDepartment.Name : null; }
    }
    
    public virtual IEnumerable<string> AdditionalExecutorDepartmentNames
    {
        get { return AdditionalExecutorDepartments.Select(x => x.Name); }
    }
    

    B.更改数据库架构,删除Department 表,并将任何Department_id 列替换为DepartmentName。如果部门真的应该是一个价值对象,而不是一个实体,请这样做。更改架构后,您的映射需要从 many-to-onebag many-to-many 更改为 propertybag element

    C.如果您想要的类似于选项“A”,但您还希望能够更改部门而不会弄乱Department_id - 如果您将Department 的主键更改为字符串,您可以获得类似的结果名称(前提是它是唯一的且不为空)。这将允许您使用 session.Load 从字符串名称中获取 Department 实例,而无需访问数据库。

    所以,所有这一切可能不是你所希望的“这是你不知道的惊人地图”的灵丹妙药,但这些都是我能想到的所有现实选择,你应该能够在此列表中找到满足您需求的东西。

    【讨论】:

      猜你喜欢
      • 2012-06-12
      • 1970-01-01
      • 1970-01-01
      • 2013-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多