NHibernate映射和查询表相关但没有外键约束

时间:2010-04-16 19:29:43

标签: nhibernate nhibernate-mapping

我对NHibernate相当新,我需要提出一些与常见情况有关的问题。以下简化示例说明了该问题。

我有两个名为Equipment和Users的表。用户是一组系统管理员。设备是一套机器。

表:

  • Users表具有UserId int和LoginName nvarchar(64)。
  • 设备表有EquipId int,EquipType nvarchar(64),UpdatedBy int。

行为:

  • 系统管理员可以对设备进行更改,当设备管理员执行更改时,设备的UpdatedBy字段“通常”设置为其用户ID。
  • 可以随时删除用户。
  • 新设备项的UpdatedBy值为null。

在Equipment.UpdatedBy上没有外键约束,这意味着:

  • Equipment.UpdatedBy可以为null。
  • Equipment.UpdatedBy值可以是=现有的User.UserId值
  • Equipment.UpdatedBy值可以是=不存在的User.UserId值

要查找设备和上次更新设备的人,我可能会这样查询:

选择E.EquipId,E.EquipName,U.UserId,U.LoginName 来自Equipment E 左外连接用户U。 E.UpdatedBy = U.UserId

足够简单。

那么如何在NHibernate中做到这一点?

我的映射可能如下:

<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
  namespace="Data"
  assembly="Data">

  <class name="User" table="Users">
    <id name="Id" column="UserId" unsaved-value="0">
      <generator class="native" />
    </id>
    <property name="LoginName" unique="true" not-null="true" />
  </class>

  <class name="Equipment" table="Equipment">
    <id name="Id" column="EquipId" type="int" unsaved-value="0">
      <generator class="native" />
    </id>
    <property name="EquipType" />
    <many-to-one name="UpdatedBy" class="User" column="UpdatedBy" />
  </class>

</hibernate-mapping>

那么我如何获得所有设备项目以及更新设备?

   using (ISession session = sessionManager.OpenSession())
   {
      List<Data.Equipment> equipList =
         session
            .CreateCriteria<Data.Equipment>()
            // Do I need to SetFetchmode or specify that I
            // want to join onto User here? If so how?
            .List<Data.Equipment>();

      foreach (Data.Equipment item in equipList)
      {
         Debug.WriteLine("\nEquip Id: " + item.Id);
         Debug.WriteLine("Equip Type: " + item.EquipType);

         if (item.UpdatedBy != null)
            Debug.WriteLine("Updated By: " + item.UpdatedBy.LoginName);
         else
            Debug.WriteLine("Updated by: Nobody");
      }
   }

当Equipment.UpdatedBy = 3并且没有Users.UserId = 3时,上述失败

我也有一种感觉,生成的SQL是从设备中选择全部,后面是UserId = n 的用户中的许多选择列,而我期望NHibernate按照普通的普通SQL左键加入,然后点击一下。如果我能告诉NHibernate一次性执行查询,我该怎么做?

时间对我的项目至关重要,因此感谢您提供的任何帮助。如果你在猜测NHibernate在这种情况下如何工作,请说你不是很确定。非常感谢。

1 个答案:

答案 0 :(得分:0)

在你的映射中,添加not-null = false,如下所示:

<many-to-one name="UpdatedBy" class="User" column="UpdatedBy" not-null="false" />

在您的代码中,请勿检查用户是否设置了国家/地区,以确定是否有人更新了该国家/地区。如果User为null,则会导致NullPointerException。而是检查User是否为null:

User user = item.UpdatedBy;
if (user  != null)
    Debug.WriteLine("Updated By: " + user.LoginName);
else
    Debug.WriteLine("Updated by: Nobody");