NHibernate <list>位置不会更新</list>

时间:2014-01-28 12:30:42

标签: c# list nhibernate

我指的是这篇文章:http://ayende.com/blog/3960/nhibernate-mapping-one-to-one

<class name="UniDirectional.UConversation, NHibernateOneToMany" table="conversation">
  <id name="Id">
    <generator class="native" />
  </id>
  <property name="Subject"/>
  <list name="MessageList" cascade="all">
    <key column="ConversationId"/>
    <index column="`Order`"/>
    <one-to-many class="UniDirectional.UMessage, NHibernateOneToMany"/>
  </list>
</class>

<class name="UniDirectional.UMessage, NHibernateOneToMany" table="message">
  <id name="Id">
    <generator class="native" />
  </id>
  <property name="Text"/>
  <property name="ConversationId" type="Int32" column="ConversationId" />
</class>

现在是C#代码:

session = factory.OpenSession();
transaction = session.BeginTransaction();

UniDirectional.UMessage message1 = new UniDirectional.UMessage();
message1.Text = "Text1";
niDirectional.UMessage message2 = new UniDirectional.UMessage();
message2.Text = "Text2";
ArrayList messageList = new ArrayList();
messageList.Add(message1);
messageList.Add(message2);

UniDirectional.UConversation someConversation = new UniDirectional.UConversation();
someConversation.Subject = "a test conversation";
someConversation.MessageList = (IList)messageList;

session.Save(someConversation);
transaction.Commit();

Assert.AreEqual(message1.ConversationId, someConversation.Id); // FAIL

message1.ConversationId总是 0 ,如果我尝试重新加载消息,则没有任何区别。 但是,如果我重新启动整个程序并加载现有消息,则ConversationId已填充正确。 为什么NHibernate不更新ConversationId

1 个答案:

答案 0 :(得分:0)

关键是,NHibernate不管理C#运行时对象。

除非我们明确地设定两种关系:

foreach(message in someConversation.MessageList)
{
    message.ConversationId = someConversation.Id; 
}

在运行时不会分配message.ConversationId。它不是NHibernate所做的

此外,如果someConversation ID是通过身份(本机)生成的,则无法正常运行,因为在调用Save()之前,someConversation.Id可能 0

我们能做的最好的事情就是将父母不是作为int而是作为UConversation

<class name="UniDirectional.UMessage, NHibernateOneToMany" table="message">
  <id name="Id">
    <generator class="native" />
  </id>
  <property name="Text"/>
  <property name="ConversationId" type="Int32" column="ConversationId" 
    insert="false" update="false />
  <many-to-one name="Conversation" column="ConversationId" />
</class>

在这里,我们使用新属性Conversation

扩展了C#实体UMessage
public virtual UConversation Conversation { get; set; }

这一个将被保留,ConversationId(映射到同一列)仍将存在,例如查询,按...排序,但不会被插入或更新

这将有助于我们在运行时正确地进行映射

foreach(message in someConversation.MessageList)
{
    message.Conversation = someConversation; // assing parent
}

但在这种情况下,message.ConversationId将不会再次自动填充,除非我们将通过NHibernate重新加载它。

最后,因为我们现在确实已经映射了两端(实体),所以我们可以使用inverse属性改进映射。这将改善WRITE操作期间的所有性能,但要求在运行时正确设置两端(从父级到父级,在父级到子级)

<list name="MessageList" cascade="all" inverse="true">