[英]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-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-one
和bag
many-to-many
更改为property
和bag
element
。
C.如果您想要的与选项“ A”类似,但是您也希望能够更改部门而不会弄乱Department_id
如果将Department
的主键更改为字符串名称,则可以获得类似的信息( (前提是它是唯一的,而不是null)。 这将允许您使用session.Load
从字符串名称获取Department实例,而无需访问数据库。
因此,所有这些可能都不是您所希望的银弹“这是您不知道的惊人映射”,但是这些都是我能想到的所有现实选择,您应该能够找到在此列表中满足您需求的东西。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.