2010-04-16 97 views
1

我對NHibernate相當新,我需要問幾個有關非常頻繁的情況的問題。以下簡化的例子說明了這個問題。NHibernate映射和查詢表相關,但沒有外鍵約束

我有兩個名爲設備和用戶的表。用戶是一組系統管理員。設備是一套機器。

表:

  • 用戶表具有用戶ID int和LoginName將nvarchar的(64)。
  • 設備表具有EquipId int,EquipType nvarchar(64),UpdatedBy int。

行爲:

  • 系統管理員可以更改設備,當他們這樣做,設備的UpdatedBy域是「正常」設置爲自己的用戶ID。
  • 用戶可隨時刪除。
  • 新設備項目有一個UpdatedBy值爲null。

有上Equipment.UpdatedBy沒有外鍵約束,這意味着:

  • Equipment.UpdatedBy可以爲空。
  • Equipment.UpdatedBy值可以是現有=價值User.UserId
  • Equipment.UpdatedBy值可以是=不存在User.UserId值

要查找設備和誰最後更新的設備,我可能查詢是這樣的:

select E.EquipId,E.EquipName,U.UserId,U.LoginName from Equipment E left outer join Users on。 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如何在這種情況下工作,請說你不是很確定。非常感謝。

回答

0

在你的地圖,添加非空=假,像這樣:

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

在你的代碼,不檢查,如果用戶有一個國家內,看它是否是由人進行更新。如果用戶爲空,則會導致NullPointerException。而是檢查用戶是否爲空:

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

謝謝。它有可能使NHibernate獲得所有的數據在一擊中? – IanT8 2010-04-16 20:47:52

+0

您可以設置一個標準來獲取連接到設備的所有用戶。或者讓所有連接有用戶的設備與以前一樣循環訪問設備。 – 2010-04-16 20:51:07

+0

你有這樣的標準API查詢的任何粗略的例子。我發現Criteria是hibernate最困難的部分。我經常查看我現有的SQL查詢並思考如何使用Criteria API來表達所有這些。 – IanT8 2010-04-16 22:13:33