【问题标题】:How do I map this relationship in nhibernate 3.0?如何在 nhibernate 3.0 中映射这种关系?
【发布时间】:2010-12-31 13:20:08
【问题描述】:

我在 NHibernate 中映射以下内容时遇到问题:

我有两张表(这些是旧表,无法更改):

tbl零件 ======= + --- ID int identity(1,1) [----------+ |名称 varchar(50) | | PartTypeID 整数 | 1:* 数量 int | | | | tblPartAssemblyItems *:1 | =====================| +-] PartID int (PK) | AssemblyItemPartID int (PK) ---------------+ 状态整数 编码 varchar(50)

tblParts.PartTypeID 告诉我们零件的类型。有几个可能的值。有一种特殊情况:

  • PartTypeID = 0 - 它告诉我们这部分由 tblPartAssemblyItems 中列出的 0 个或多个子部分组成。
  • PartTypeID = 1 - 这是一个完整的独立部分
  • PartTypeID = 2 - 这部分是用来补其他部分的

PartID 是一个外键值tblParts.IDAssemblyItemPartID 引用 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 以获取PartAssemblyItemName

如果这是 T-SQL,我会做这样的事情来选择所有部分及其组成部分:

SELECT p.ID, p.Name, p.PartTypeID, i.AssemblyItemPartID, 
       i.Status, i.Coding, 
       p2.Name AS AssemblyItemPartName
FROM tblParts p
LEFT JOIN tblPartAssemblyItems i ON p.ID = i.PartID
-- This join here to get the subassembly name
LEFT JOIN tblParts p2 ON i.AssemblyItemPartID = p2.ID
WHERE p.PartTypeID <> 2 
ORDER BY p.ID

如何以“NHibernate”方式执行此操作,我可以使用 HQL 重新加入 Part/tblParts 吗?

【问题讨论】:

    标签: c# .net nhibernate c#-4.0 nhibernate-mapping


    【解决方案1】:

    tblPartAssemblyItems 没有 Name 列,所以不要映射它。如果你真的想在你的类中使用它,那么定义一个自定义 getter,它返回连接实体的名称。

    【讨论】:

    • 感谢您的回复。我已经澄清了我需要做什么。
    • 我想我明白了。您询问映射 name 属性令人困惑,这不是您所需要的。问题似乎是 tblPartAssemblyItems.PartID 是主键的一部分,也是外键,对吧?嗯,我不认为这是可能的。无论如何,单独映射外键意味着使用 映射元素,并且在您的代码中,您将有一个 Part 引用而不是 PartID 整数。检查您是否可以在 . 中使用它
    • 好的...您对将零件参考沉没的评论...我想我有一个可行的解决方案。谢谢。 ps:您应该将您的评论编辑到您的答案中。
    【解决方案2】:

    借助fejesjoco 的评论,在PartAssemblyItem 中有Part 参考,我想我已经解决了这个问题:

    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 的这篇文章也完成了这个圈子:

    NHibernate Mapping - one-to-one

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-17
      • 2012-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多