3

我想弄清楚如何使用CompositeId來映射另一個類。這是一個測試案例:流利的NHibernate複合材料到映射類

的表格:

TestParent: 
    TestParentId (PK) 
    FavoriteColor 

TestChild: 
    TestParentId (PK) 
    ChildName (PK) 
    Age 

的類在C#:

public class TestParent 
{ 
    public TestParent() 
    { 
     TestChildList = new List<TestChild>(); 
    } 

    public virtual int TestParentId { get; set; } 
    public virtual string FavoriteColor { get; set; } 
    public virtual IList<TestChild> TestChildList { get; set; } 
} 

public class TestChild 
{ 
    public virtual TestParent Parent { get; set; } 
    public virtual string ChildName { get; set; } 
    public virtual int Age { get; set; } 

    public override int GetHashCode() 
    { 
     return Parent.GetHashCode()^ChildName.GetHashCode(); 
    } 

    public override bool Equals(object obj) 
    { 
     if (obj is TestChild) 
     { 
      var toCompare = obj as TestChild; 
      return this.GetHashCode() != toCompare.GetHashCode(); 
     } 
     return false; 
    } 
} 

的功能NHibernate地圖:

public class TestParentMap : ClassMap<TestParent> 
{ 
    public TestParentMap() 
    { 
     Table("TestParent"); 
     Id(x => x.TestParentId).Column("TestParentId").GeneratedBy.Native(); 
     Map(x => x.FavoriteColor); 

     HasMany(x => x.TestChildList).KeyColumn("TestParentId").Inverse().Cascade.None(); 
    } 
} 

public class TestChildMap : ClassMap<TestChild> 
{ 
    public TestChildMap() 
    { 
     Table("TestChild"); 
     CompositeId() 
      .KeyProperty(x => x.ChildName, "ChildName") 
      .KeyReference(x => x.Parent, "TestParentId"); 

     Map(x => x.Age); 
     References(x => x.Parent, "TestParentId"); /** breaks insert **/ 
    } 
} 

當我嘗試添加一個新的記錄,我得到這個錯誤:

System.ArgumentOutOfRangeException : Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index

我知道這個錯誤是由於TestParentId列被映射到CompositeId和References調用中。但是,根據TestParentId查詢TestChild時刪除引用調用會導致另一個錯誤。

下面是確實的查詢代碼:

var session = _sessionBuilder.GetSession(); 
using (var tx = session.BeginTransaction()) 
{ 
    // create parent 
    var p = new TestParent() { FavoriteColor = "Red" }; 
    session.Save(p); 

    // creat child 
    var c = new TestChild() 
       { 
        ChildName = "First child", 
        Parent = p, 
        Age = 4 
       }; 
    session.Save(c); // breaks with References call in TestChildMap 

    tx.Commit(); 
} 

// breaks without the References call in TestChildMap 
var children = _sessionBuilder.GetSession().CreateCriteria<TestChild>() 
    .CreateAlias("Parent", "p") 
    .Add(Restrictions.Eq("p.TestParentId", 1)) 
    .List<TestChild>(); 

關於如何創建這個場景組合鍵任何想法?

回答

11

我找到了一個更好的解決方案,可以查詢和插入。關鍵是更新TestChild的映射以不插入記錄。新地圖是:

public class TestChildMap : ClassMap<TestChild> 
{ 
    public TestChildMap() 
    { 
     Table("TestChild"); 
     CompositeId() 
      .KeyProperty(x => x.ChildName, "ChildName") 
      .KeyReference(x => x.Parent, "TestParentId"); 

     Map(x => x.Age); 
     References(x => x.Parent, "TestParentId") 
      .Not.Insert(); // will avoid "Index was out of range" error on insert 
    } 
} 
+1

你剛剛度過了我的一天!非常感謝提問者和回答者!我也能夠解決這個問題,它可以用一種方式插入,但不能讀取,反之亦然,但不會猜到這是解決方案。 – Sam 2014-07-11 03:56:19

+0

解決方案適合我,特別是代碼行.Not.Insert() – Anil 2017-03-28 09:44:58

2

您不能修改您的查詢的任何理由,只是

_sessionBuilder.GetSession().CreateCriteria<TestChild>() 
    .Add(Restrictions.Eq("Parent.TestParentId", 1)) 
    .List<TestChild>() 

然後擺脫參考的?

+0

感謝 - 工作。 我不知道這會解決所有出現(可能需要加入TestChild和TestParent其他查詢),但我想關於我以後會擔心。 – 2011-03-21 16:23:14