2010-03-30 95 views
1

我一直在破壞我的想法如何讓我的標籤實體 的工作。我會馬上到一些數據庫的結構:NHibernate - 映射標籤的實體

tblTag 
TagId - int32 - PK 
Name 

tblTagEntity 
TagId - PK 
EntityId - PK 
EntityType - string - PK 

tblImage 
ImageId - int32 - PK 

tblBlog 
BlogId - int32 - PK 

class Image 
Id 
EntityType { get { return "MyNamespace.Entities.Image"; } 
IList<Tag> Tags; 

class Blog 
Id 
EntityType { get { return "MyNamespace.Entities.Blog"; } 
IList<Tag> Tags; 

明顯的問題,我這裏是的EntityType是IDENTIFER但 在數據庫中不存在。如果有人可以幫助這個映射,我會非常感謝。

+0

見我的回答,我增加了一些更多的代碼。 – 2010-03-30 14:52:35

+0

添加了一些性能註釋以添加/刪除標籤。順便說一下,在這裏附近的好獨角獸:-) – 2010-04-01 07:01:03

回答

0

您不需要實體類型。看看任何類型的映射(它將類型名稱存儲在關係表中的數據庫中,但實體模型中不需要它)。

參見this blog post by ayende


編輯:試圖寫的例子。

你可以爲每個標記的對象,一個自己的表,這是簡單,直接的,你甚至不需要任何類型:

<class name="Tag"> 
    <!-- ... --> 
    <property name="Name"/> 
</class> 

<class name="Image"> 
    <!-- ... --> 
    <bag name="Tags" table="Image_Tags"> 
    <key column="Image_FK"/> 
    <many-to-many class="Tag" column="TagId "/> 
    </bag> 
</class> 

嘗試使用一些先進的功能,它映射到一個單一的表,但我認爲它不會以這種方式工作:

<class name="Tag"> 
    <!-- ... --> 
    <property name="Name"/> 
    <bag name="Objects" table="tblTagEntity" access="noop"> 
    <key column="TagId"/> 
    <many-to-any id-type="System.Int64" meta-type="System.String"> 

     <meta-value 
     value="IMAGE" 
     class="Image"/> 
     <meta-value 
     value="BLOG" 
     class="Blog"/> 

     <column name="EntityType"/> 
     <column name="EntityId"/> 
    </many-to-any> 
    </bag> 
</class> 

<class name="Image"> 
    <!-- ... --> 
    <bag name="Tags" table="tblTagEntity" where="EntityType='IMAGE'"> 
    <key column="EntityId"/> 
    <many-to-many class="Tag" column="TagId "/> 
    </bag> 
</class> 

的位置招數:

  • access="noop"指定實體模型中沒有屬性的外鍵,see this post
  • where="EntityType='IMAGE'"過濾加載的數據。

問題是最有可能的EntityType沒有設置爲任何有用的值。這可以在某個地方解決,但我認爲這不值得。

其他人可能有更好的主意。


編輯2:另一個(工作)溶液

使關聯表的實體:

在短

  • 標籤=> TagEntity:未映射或一個(noop)
  • TagEntity =>標籤:多對一
  • TagEntity =>對象:任何
  • 對象=> TagEntity:一個一對多的逆

這應該直截了當。

類:

class Tag 
{ 
    string Name { get; set; } 
} 

class TagEntity 
{ 
    Tag Tag { get; set; } 
    object Entity { get; set; } 
} 

class Image 
{ 
    IList<TagEntity> tags { get; private set; } 
} 

唯一的缺點似乎是,你必須確保雙向關聯是不裝載大量的數據是一致的。請注意,反向收集不會被存儲。


編輯2:性能說明

當您添加/移除標籤,你可以做一個伎倆。 TagEntity具有對標記實體的引用。該實體也有一個TagEntities的列表,但是這被標記爲反向。 (這意味着它們已被加載,但未被存儲。)

您可以在不加載實體的情況下添加和刪除標籤,而無需加載所有標籤。

添加:

  • 獲取標記添加(或負載代理,如果你有標籤的ID)
  • 負荷實體(只是代理,使用session.Load,在這裏沒有DB訪問)
  • 創造新TagEntity,分配標籤和實體代理
  • 保存TagEntity

刪除:

  • 獲取Tag實體以移除
  • 刪除TagEntity。

在會話中,您沒有將此標籤分配給TagEntity或從TagEntity中移除。這很好地工作,假設您只在此事務中添加或刪除標記。

我在標籤上定義了一個TagEntities列表,你可以做同樣的事情,不用加載所有的TagEntities來添加或刪除它。

+0

好吧,但我需要TagEntity作爲一個實體嗎?那麼在那種情況下,這個映射將如何呢?我已經看過任何和許多對任何人都沒有得到任何智慧=/ – ZNS 2010-03-30 13:51:29

+0

不,你不需要TagEntity,如果沒有更多的屬性。只需將它映射爲''。 – 2010-03-30 13:55:39

+0

謝謝。不過,我已經閱讀了20次我認爲的博客帖子,但仍然無法在我的場景中實現。問題是我的情況是相反的。我需要添加一種類型的實體給其他人。 – ZNS 2010-03-30 13:59:34

0

你可以在你的代碼中使EntityType成爲Enum。和/或,你可以嘗試讓EntityType成爲數據庫中的一個實際實體(tblEntityType)。

0

得到Stefans最終解決方案的工作!這是我的最終映射:

圖片

<bag name="TagEntites" table="tblTagEntity" cascade="all" fetch="join" inverse="true" where="EntityType='EntityImage'"> 
<key column="EntityId"></key> 
<one-to-many class="TagEntity" /> 
</bag> 

TagEntity

<id name="Id"> 
    <column name="TagEntityId"></column> 
    <generator class="identity" /> 
</id> 
<any name="Entity" id-type="System.Int32" meta-type="System.String"> 
    <meta-value value="EntityImage" class="Image" /> 
    <column name="EntityType"></column> 
    <column name="EntityId"></column> 
</any> 
<many-to-one name="Tag" class="Tag" cascade="all" fetch="join"> 
    <column name="TagId"></column> 
</many-to-one>