繁体   English   中英

NHibernate-映射多对一和多对多查找表关系,而无需使用第二类

[英]NHibernate - mapping many-to-one and many-to-many lookup table relationships without using a second class

我正在映射的数据库包含Plan实体。 每个计划实体都有一个主要部门(多对一关系)和一包可能的其他部门(多对多关系)。 部门存储在仅具有“ 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>元素来获取主部门,但显然它只能在主键上进行<Join> (请参阅https://nhibernate.jira.com/browse/NH-1452 )。

部门类很可能并非完全没有用。 以下代码是什么意思?

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

您无法判断我们是要修正拼写还是将其分配给其他部门。

部门名称是否有可能更改? 如果是这样,是否需要在属于该部门的所有计划中反映这种变化? 如果是这样,那么从域驱动设计的角度来看,部门是一个实体,而不是价值对象。 如果是实体,则应继续使用many-to-onemany-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-onebag many-to-many更改为propertybag element

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM