我指的是这篇文章: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
?
答案 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#实体UMessagepublic 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">