2012-03-04 80 views
3

我有一個應用程序存儲樹結構,並能夠生成數據庫正常,但是當插入時我得到一個異常。我簡化了代碼以縮小問題範圍。FluentNHibernate和持久化的樹結構

類來保存:

public class Node 
{ 
    public virtual int NodeId { get; set; } 
    public virtual string Name { get; set; } 
    public virtual Node Parent { get; set; } 
    public virtual IList<Node> Children { get; set; } 
} 

這是映射代碼:

public sealed class NodeMap : ClassMap<Node> 
{ 
    public NodeMap() 
    { 
     Id(n => n.NodeId).GeneratedBy.Identity(); 
     Map(n => n.Name); 
     References(n => n.Parent).LazyLoad().Nullable(); 
     HasMany(n => n.Children).LazyLoad().KeyColumn("ParentId"); 
    } 
} 

當我做一個插入像dataClient.Insert(new Node { Name = "Test" });我得到一個異常說:

的NHibernate .Exceptions.GenericADOException:無法插入:[Model.Node] [SQL:INSERT INTO [Node](Name,NodeId)VALUES(?,?);選擇SCOPE_IDENTITY()]

而且內部異常說:

System.Data.SqlClient.SqlException:無法在表中插入的標識列的顯式值 '節點' 當IDENTITY_INSERT設置爲OFF。

這實際上是完全可以理解的,但我只是想知道爲什麼它試圖爲NodeId設置一個顯式值。當我刪除引用部分時,插入會通過,所以它必須以某種方式與此相關。

FluentNHibernate的版本是1.2.0.712,NHibernate的版本是3.1.0.4000。

回答

2

這是因爲默認列爲typename + id的引用恰好與id列的名稱相同。在參考中明確指出它。

References(n => n.Parent, "ParentId").LazyLoad().Nullable(); 

更新:作爲慣例

public class ReferenceColumnConvention : IReferenceConvention 
{ 
    public void Apply(IManyToOneInstance instance) 
    { 
     // uncomment if needed 
     //if (instance.EntityType == instance.Property.PropertyType) 
     instance.Column(instance.Name + "id"); 
    } 
} 
+0

謝謝,FIRO。這解決了問題,而且它確實有道理。 – 2012-03-05 21:51:13

+0

是否可以讓約定來處理這個問題:如果屬性的類型與宿主類型相同,那麼它應該回退到propertyname + id?這在我認爲的大多數情況下都是有用的。 – 2012-03-05 22:02:35