Nhibernate IList映射到子子表

时间:2015-04-18 06:03:27

标签: c# c#-4.0 nhibernate nhibernate-mapping

类别:

[DataContract]
public class Parent
{
    public virtual long Id { get; set; }

    public virtual string Name  { get; set; }

    [DataMember]
    public virtual IList<string> Values { get; set; }

    public Parent()
    {

    }
}

ORM映射文件:

<class name="Testing.Models.Parent" table="Parent"  >
    <id name="Id">
      <generator class="native" />
    </id>
    <property name="Name" />
    <list name="Values" table="ChildValue" inverse="true" >
      <key column="ParentId" />
      <index column="Sequence" type="System.Int32"/>
      <element column="Value" type="System.String"/>
    </list>
</class>

但是在使用父实体的保存进行测试时,它只会插入到父表中。 ChildValue表未插入任何记录,但我提供了值。

我发现反向必须是真的,即使它不起作用。

[更新:插入代码] 创建方法

public IList<Parent> Create(IList<Parent> entities)
{
 using (ISession session = SessionFactory.OpenSession())
    {
       foreach (var entity in entities)
         {
            session.Save(entity);
        }
         return entities;
    }
}

ISessionFactory使用Unity注入并配置为

UnityContainer.RegisterInstance(typeof(ISessionFactory),
                new NHibernate.Cfg.Configuration().Configure().BuildSessionFactory());

虽然nhibernate配置类似于(在app.config中)

<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2"  >
    <session-factory>
      <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
      <property name="dialect">NHibernate.Dialect.MsSql2012Dialect,NHibernate</property>
      <property name="connection.connection_string_name">db</property>
      <!-- set show_sql property to false on production-->
      <property name="show_sql">true</property>
      <mapping assembly="Testing"/>
    </session-factory>
  </hibernate-configuration>

创建实体的测试方法是

[TestMethod]
        public void TestCreate()
        {
            IList<Parent> entities = new List<Parent>();
            for (int index = 0; index < 5; index++)
            {
                var entity = TestHelper.CreateEntity<Parent>();
                entity.Values = new List<string>();
                entity.Values.Add("Values" + index);
                entities.Add(entity);
            }
            entities = instance.Create(entities);

            VerifyPickList(entities, "Create");

            Assert.AreEqual(5, (int)TestHelper.Execute("SELECT COUNT(*) FROM" +
                " [dbo].[Parent]"), "Create is wrong.");
        }

[update 2:sql]

-- parent table
CREATE TABLE [dbo].[Parent](
    [Id] [int] IDENTITY(1,1) NOT NULL PRimary Key,
    [Name] [varchar](45) NOT NULL,
)

-- child table
CREATE TABLE [dbo].[ChildValue](
    [ParentId] [int] NOT NULL,
    [Value] [varchar](45) NOT NULL,
    [Sequence] [int] NOT NULL,
 CONSTRAINT [PK__Parent__D099C8FD03317E3D] PRIMARY KEY CLUSTERED 
(
    [ParentId] ASC,
    [Value] ASC
)


ALTER TABLE [dbo].[ChildValue]  WITH CHECK ADD  CONSTRAINT [pk_plv_pl] FOREIGN KEY([ParentId])
REFERENCES [dbo].[Parent] ([Id])
GO

ALTER TABLE [dbo].[ChildValue] CHECK CONSTRAINT [pk_plv_pl]
GO

1 个答案:

答案 0 :(得分:1)

最重要的是使用 inverse="true"

<list name="Values" table="ChildValue" 
    // inverse="true" is NO OPTION for element lists
    inverse="false" // inverse="false" or nothing
  >
  <key column="ParentId" />
  <index column="Sequence" type="System.Int32"/>
  <element column="Value" type="System.String"/>
 </list>

重点是,NHibernate将此设置视为:“另一端将关心持久性......”如果有一个类<one-to-many>,这是可以的。但不行,如果有<element>

Class (映射为one-to-many是第一级公民,可以关心持久性...... string 不能

此代码现在应该对两个表执行INSERT:

var parent = Parent { Name = "abc" };
parent.Values  = new List<string> { "testValue" };
session.Save(parent);

检查文档,例如

以示例:

<set name="Aliases" table="person_aliases" sort="natural">
    <key column="person"/>
    <element column="name" type="String"/>
</set>

查看此文章了解更多详情: