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