Nat*_*ari 9 linq nhibernate linq-to-nhibernate
我们的应用程序具有故事的概念和标签的概念.故事可以应用许多标签,标签可以应用于许多故事,使关系多对多.这两个表,故事和标签与第三个StoriesToTags桥接.
映射文件的相关部分如下:
这是从Story到Tag的映射:
<class name="Story" table="Stories">
...
<set fetch="subselect" name="Tags" table="StoriesToTags">
<key>
<column name="StoryId" />
</key>
<many-to-many class="Tag">
<column name="TagId" />
</many-to-many>
</set>
</class>
Run Code Online (Sandbox Code Playgroud)
以及从Tag到Story的反向关系:
<class name="Tag" table="Tags">
...
<set fetch="subselect" inverse="true" name="Stories" table="StoriesToTags">
<key>
<column name="TagId" />
</key>
<many-to-many class="Story">
<column name="StoryId" />
</many-to-many>
</set>
</class>
Run Code Online (Sandbox Code Playgroud)
如您所见,我们使用子选择提取策略来避免N + 1查询问题.一切都很好,直到您尝试使用LINQ分页结果:
IQueryable<Story> stories = GetStories(...).TakePage(pageNumber, pageSize);
Run Code Online (Sandbox Code Playgroud)
运行此查询后,NHibernate将删除未在查询中加载的所有故事的关系(StoriesToTags中的记录).它似乎只在标记被特定加载时发生(即,触发子选择).如果我们切换到连接或选择获取策略,则不会删除关系,但这会导致执行N + 1个查询.
我最好的猜测是NHibernate认为标签已经成为孤儿,但我们没有在集合上设置任何级联.另外,据我所知,设置级联没有任何效果.
这个过程在NHibernate 2.x和NHibernate.Linq下运行良好.在我们转移到内置LINQ支持的NHibernate 3.x之前,我们没有看到删除问题.我不确定它有什么不同,但是对于它的价值,我们使用带有身份密钥的SQL Server.
有什么想法吗?我最初认为我做的事情非常愚蠢,但我基本上尝试了映射的每个排列,我们似乎无法消除这个问题.
编辑:另一个有趣的信息.如果session.IsDirty()
在关闭会话之前调用,则不会发生此问题.我怀疑这是因为集合更改不会在刷新之间保持不变,但我不能很好地解释NHibernate的源代码以确定.