0

我正在映射的数据库包含计划实体。每个计划实体都有一个主要部门(多对一关系)和一组可能的附加部门(多对多关系)。部门存储在只有“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; }
}

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

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

4

1 回答 1

1

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

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

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

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

plan.ExecutorDepartment.Name = "Human Resources";

...或将计划分配给新部门,您说:

plan.ExecutorDepartment = theOtherHrDepartmentThatActuallyCaresAboutSpelling;

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

NHibernate 是一个允许您以面向对象、域驱动的方式使用关系数据库的工具。当您尝试遵循 DDD 规则时,它的效果最好。从 DDD 的角度来看,您要求做的事情没有意义,因为 Department确实有一个身份,所以 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-oneand更改bag many-to-manypropertyand bag element

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

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

于 2013-11-01T20:53:55.917 回答