2011-03-11 44 views
2

我試圖映射包含其值的唯一鍵約束的組件列表。NHibernate使用唯一鍵約束映射組件列表

A '修剪' 的類的樣品均低於:

public class MyObject 
{ 
    public virtual int Id { get; set; } 
    public virtual IList<Alias> Aliases { get; set; } 
} 

public class Alias 
{ 
    public Alias(string type, string value) 
    { 
     Type = type; 
     Value = value; 
    } 

    public virtual string Type { get; protected set; } 
    public virtual string Value { get; protected set; } 
} 

而且從MyObject的相關NHibernate的映射(類型已被修整爲簡潔起見):

<list cascade="all-delete-orphan" name="Aliases" table="MyObject_Aliases" mutable="true"> 
     <key> 
     <column name="MyObject_id" /> 
     </key> 
     <index> 
     <column name="`Index`" /> 
     </index> 
     <composite-element class="Alias"> 
     <property name="Type" type="System.String"> 
      <column name="Type" unique-key="UK_Alias" /> 
     </property> 
     <property name="Value" type="System.String"> 
      <column name="Value" unique-key="UK_Alias" /> 
     </property> 
     </composite-element> 
    </list> 

的目的是防止兩個MyObjects包含相同的別名。

當向MyObject添加新的別名時,這非常有效。但是,如果您要從刪除別名後的別名列表中刪除別名,那麼NHibernate會嘗試重新排列導致密鑰違規的列表。

是NHibernate的正在生成SQL的樣品是:

-- statement #1, saving MyObject.Aliases 
INSERT INTO MyObject_Aliases 
      (MyObject_id, 
      "Index", 
      Type, 
      Value) 
VALUES  (101 /* @p0 */, 
      0 /* @p1 */, 
      'A' /* @p2 */, 
      'ALIAS1' /* @p3 */) 

INSERT INTO MyObject_Aliases 
      (MyObject_id, 
      "Index", 
      Type, 
      Value) 
VALUES  (101 /* @p0 */, 
      1 /* @p1 */, 
      'A' /* @p2 */, 
      'ALIAS2' /* @p3 */) 

-- statement #2, updating MyObject.Aliases after removing the first list item 
UPDATE MyObject_Aliases 
SET Type = 'A' /* @p0 */, 
     Value = 'ALIAS2' /* @p1 */ 
WHERE MyObject_id = 101 /* @p2 */ 
     AND "Index" = 0 /* @p3 */ 

聲明#2在這個例子中拋出:

NHibernate.Exceptions.GenericADOException : could not update collection rows: [MyObject.Aliases#101][SQL: UPDATE MyObject_Aliases SET Type = ?, Value = ? WHERE MyObject_id = ? AND "Index" = ?] 
    ----> System.Data.SQLite.SQLiteException : Abort due to constraint violation 
columns Type, Value are not unique 

例外本身就是基於什麼是真正發生的事情非常有意義,但我如何才能實現預期的實際工作?

+1

您是否需要使用列表映射,或者可以使用集合嗎? – Vadim 2011-03-11 16:31:40

+0

除了我自己的無知之外,似乎沒有任何理由我不能使用一個集合,事實上它似乎表現得像我期望的那樣,而不必實現我自己的比較器,這並不是什麼大問題。如果你願意將你的評論轉換爲我的實際答案,我很樂意將這個問題標記爲答案! – 2011-03-11 17:19:22

+0

如果需要'list' mapping **是什麼解決方案? – MarioDS 2016-09-08 15:28:51

回答

1

如果你的集合不需要建立索引,你應該使用集合映射。一個集合是一個確保沒有重複的集合類型。列表是可以編入索引的集合類型。

+0

我確實失去了使用索引訪問我的集合的能力,但是在LINQ中,通過集合篩選更容易。 – 2011-03-11 17:24:12

+0

@Chris,你仍然可以在代碼中索引你的集合,通過公開List作爲屬性,一個很好的例子可以在這裏找到http://stackoverflow.com/questions/824587/how-to-map-a-collectiont- in-nhibernate – Vadim 2011-03-11 17:26:25

+0

我有和這個問題完全相同的問題,但真正需要使用'list'映射。我怎樣才能解決這個問題呢? – MarioDS 2016-09-08 15:28:38