我无法在NHibernate中映射以下内容:
我有两个表(这些是遗留的,不能更改):
tblParts ======= + --- ID int identity(1,1) [----------+ | Name varchar(50) | | PartTypeID int | 1:* Quantity int | | | | tblPartAssemblyItems *:1 | ==================== | +-] PartID int (PK) | AssemblyItemPartID int (PK) ---------------+ Status int Coding varchar(50)
tblParts.PartTypeID
告诉我们部件的类型。有几个可能的值。有一个特殊情况:
PartTypeID
= 0 - 它告诉我们此部分由tblPartAssemblyItems
中列出的0个或更多子部分组成。PartTypeID
= 1 - 这是一个完整的独立部分PartTypeID
= 2 - 此部分用于构成其他部分 PartID
是外键值tblParts.ID
。
AssemblyItemPartID
tblParts
引用了tblParts.ID
中的部分记录。
子部分永远不会由其他子部分组成,这样可以将嵌套保持在一个深度。
PartID + AssemblyItemPartID
形成复合主键。
在我的代码中,我有:
public class Part
{
public virtual int ID { get; set; }
public virtual string Name { get; set; }
public virtual int PartTypeID { get; set; }
public virtual int Quantity { get; set; }
public virtual IList<PartAssemblyItem>
}
public class PartAssemblyItem
{
public virtual int PartID { get; set; }
public virtual int AssemblyItemPartID { get; set; }
public virtual int Status { get; set; }
public virtual string Coding { get; set; }
public virtual string Name { get; set; }
public override bool Equals(object obj) { .. snipped .. }
public override int GetHashCode() { .. snipped .. }
}
我的基本映射工作正常:
<class name="Part" table="tblParts">
<id name="ID">
<column name="ID" sql-type="int" not-null="true"/>
<generator class="identity" />
</id>
<property name="Name"/>
<property name="PartTypeID"/>
<bag name="PartAssemblyItems">
<key column="PartID"/>
<one-to-many class="PartAssemblyItem"/>
</bag>
</class>
<class name="PartAssemblyItem" table="tblPartAssemblyItems">
<composite-id>
<key-property name="PartID" column="PartID"/>
<key-property name="AssemblyItemPartID" column="AssemblyItemPartID"/>
</composite-id>
<property name="Status" />
<property name="Coding" />
<property name="Name" /> <-- How do I map this?
</class>
但我不知道如何加入/回顾tblParts
以获取Name
的{{1}}。
如果这是T-SQL,我会做这样的事情来选择所有零件及其零件构成:
PartAssemblyItem
如何以“NHibernate”方式执行此操作,我可以使用HQL连接回Part / tblParts吗?
答案 0 :(得分:2)
tblPartAssemblyItems没有Name列,因此不要映射它。如果你真的想在你的类中使用它,那么定义一个自定义的getter,它返回已连接实体的名称。
答案 1 :(得分:0)
有关Part
的{{1}}引用PartAssemblyItem
的评论帮助,我认为我已经解决了这个问题:
public class PartAssemblyItem
{
public virtual int PartID { get; set; }
public virtual int AssemblyItemPartID { get; set; }
public virtual int Status { get; set; }
public virtual string Coding { get; set; }
// public virtual string Name { get; set; } <--- DELETED THIS
// Then added this:
public virtual Part Part { get; set; }
public override bool Equals(object obj) { .. snipped .. }
public override int GetHashCode() { .. snipped .. }
}
已配置的PartAssemblyItem.hbm.xml
映射为:
<class name="PartAssemblyItem" table="tblPartAssemblyItems">
<composite-id>
<key-property name="PartID" column="PartID"/>
<key-property name="AssemblyItemPartID" column="AssemblyItemPartID"/>
</composite-id>
<property name="Status" />
<property name="Coding" />
<!-- The magic happens here -->
<many-to-one name="Part" class="Part" column="AssemblyItemPartID" />
</class>
所以现在我可以得到一份零件清单,然后看看它们的组成部分:
using(ISession session = partsDB.OpenSession())
{
using (var tx = session.BeginTransaction())
{
IList<Part> parts =
session
.CreateQuery("select p from Part as p where p.PartTypeID <> 2")
.List<Part>();
foreach (Part part in parts)
{
Console.WriteLine("{0} - {1}", part.ID, part.Name);
foreach (PartAssemblyItem subPart in part.PartAssemblyItems)
{
Console.WriteLine("--> {0} - {1}", subPart.Part.ID, subPart.Part.Name);
}
}
}
}
Ayende的这篇文章也完成了这个圈子: