2010-10-21 58 views
0

我正在使用NHibernate將我的Item類保留到SQL數據庫。 Item類有一個屬性Item.Tags類型ICollection<Tag>我正在使用以下NHibernate configation映射。防止使用多對多NHibernate映射的重複標記名稱

<set name="Tags" table="TagLinks" cascade="all" lazy ="false"> 
    <key column="ItemId" /> 
    <many-to-many class="Tag" column="TagID" /> 
</set> 

另外這裏是我的標記類的映射,它只是一個int ID和一個字符串名稱。

<class name="RCL.Tag" table="Tags" lazy="false" > 
    <id name ="TagID" column="TagID" > 
     <generator class="native"/> 
    </id> 
    <property name="Name" not-null="true"/> 
</class> 

這一切工作正常,但它允許使用相同的名稱創建重複的標籤。因此,下面的代碼將在標籤表中創建三個單獨的「foo」條目,並且都帶有單獨的ID。

myItem1.Tags.Add(new Tag("Foo")); 
myItem2.Tags.Add(new Tag("Foo")); 
myItem3.Tags.Add(new Tag("Foo")); 

這顯然不是我想要這個工作。我可以添加一個唯一的約束到Tags.Name列,但是上面的代碼只會引發異常。

在對象模型方面,我希望能夠通過編輯TagString的集合簡單地添加和刪除Item中的標籤。但是,當我的項目被保存到數據庫時,它應該確定需要創建哪些新標記以及何時應該映射到標記表中的現有條目。

我也算這個不斷變化的值基於一個一對多的關係,其中Item.Tags,簡直是一個IList<String>並會映射到同一個標籤表中的條目爲每個Item每一個人標籤。這也會起作用,但我認爲我會更喜歡第一個,因爲它會使找到具有特定標籤的項目更加高效。我對關係數據庫也很陌生。所以我甚至不確定這是否應該是一個問題。

+0

我很好奇爲什麼你真的希望這是一個數據庫解決方案? – Iain 2010-11-06 01:35:01

+0

我不確定我是否理解你的評論。數據庫解決方案的替代選擇是什麼? – 2010-11-06 18:36:06

回答

0

擁有兩個具有相同名稱的標記實體是無用的,因爲您必須按名稱搜索,否則結果將不符合您的期望。

因此,唯一可能的解決方案是您已經考慮的解決方案:使Tag.Name唯一,或完全移除實體並將標籤映射爲ICollection。

由於空間是便宜,你會被索引反正該列,後者是一個更簡單的方法,如果你想計算器般的標籤管理(同義詞等)

0

如果你雖然你失去了彈性小想嘗試DDD,那麼解決方案將是這個樣子:

public class Item 
{ 
    public IList<Tag> Tags {get;set;} 
    public void AddTag(String tagName) 
    { 
    var tagAlreadyExists = Tags.Any(a=>String.Compare(a.Name,tagName,StringComparison.OrdinalIgnoreCase)==0; 
    if (tagAlreadyExists) 
     return; // Or throw exception 
    Tags.Add(new Tag(tagName)); 
    } 
} 

基本上聚合根(項目)負責執行該標籤必須是唯一的規則。