如何在 nhibernate 3.0 中映射这种关系?

发布于 2024-10-09 13:22:06 字数 3300 浏览 0 评论 0原文

我在 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.ID 引用tblParts 中的零件记录。

子部分永远不会由其他子部分组成,从而使嵌套保持在一层深度。

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 PartAssemblyItem

如果这是 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

How do I do this in an "NHibernate" way, can I use HQL to join back to Part/tblParts?

I'm having trouble mapping the following in NHibernate:

I have two tables (these are legacy and can't be altered):

       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 tells us the type of part. There are several possible values. There is a special condition where:

  • PartTypeID = 0 - it tells us that this part is made up of 0 or more sub parts listed in tblPartAssemblyItems.
  • PartTypeID = 1 - this is a complete standalone part
  • PartTypeID = 2 - this part is used to make up other parts

PartID is a foreignkey value tblParts.ID.
AssemblyItemPartID references a part record in tblParts by tblParts.ID.

A sub-part will never ever be made up of other subparts which keeps the nesting to one level deep.

PartID + AssemblyItemPartID form a composite primary key.

In my code I have:

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 .. }
}

I've got my basic mapping working just fine:

<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>

However I don't know how to join/look back to tblParts to get the Name of the PartAssemblyItem.

If this was T-SQL I'd do something like this to select all parts and their part makeup:

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

How do I do this in an "NHibernate" way, can I use HQL to join back to Part/tblParts?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一个人的旅程 2024-10-16 13:22:06

tblPartAssemblyItems 没有 Name 列,因此不要映射它。如果您确实希望在您的类中使用它,请定义一个自定义 getter,它返回连接实体的名称。

tblPartAssemblyItems doesn't have a Name column, so don't map it. If you really want it in your class, then define a custom getter which returns the name of the joined entity.

坠似风落 2024-10-16 13:22:06

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 映射 - 一-一对一

With the help fejesjoco's comment about having a Part reference in PartAssemblyItem I think I've solved this:

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 .. }
}

The configured my PartAssemblyItem.hbm.xml mapping as:

<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>

So now I can get a list of parts and walk their part makeup:

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);
      }
    }
  }
}

Also this article by Ayende completed the circle:

NHibernate Mapping - one-to-one

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文