Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/visual-studio/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
NHibernate 3.x在组合LINQ分页、多对多和子选择获取时删除子实体_Linq_Nhibernate_Linq To Nhibernate - Fatal编程技术网

NHibernate 3.x在组合LINQ分页、多对多和子选择获取时删除子实体

NHibernate 3.x在组合LINQ分页、多对多和子选择获取时删除子实体,linq,nhibernate,linq-to-nhibernate,Linq,Nhibernate,Linq To Nhibernate,我们的应用程序有故事和标记的概念。一个故事可以应用多个标记,一个标记可以应用于多个故事,使关系成为多对多。两个表,Stories和标记与第三个表,StoriesToTags连接起来 映射文件的相关部分如下所示: 以下是从故事到标记的映射: <class name="Story" table="Stories"> ... <set fetch="subselect" name="Tags" table="StoriesToTags"> <key>

我们的应用程序有故事标记的概念。一个故事可以应用多个标记,一个标记可以应用于多个故事,使关系成为多对多。两个表,Stories标记与第三个表,StoriesToTags连接起来

映射文件的相关部分如下所示:

以下是从故事标记的映射:

<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>
<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>

...
以及从标记到故事的反向关系:

<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>
<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>

...
如您所见,我们使用subselect获取策略来避免N+1查询问题。一切都很好,直到您尝试使用LINQ页面显示结果:

IQueryable<Story> stories = GetStories(...).TakePage(pageNumber, pageSize);
IQueryable stories=GetStories(…).TakePage(页码、页面大小);
运行此查询后,NHibernate将删除查询中未加载的所有故事的关系(StoriesToTags中的记录)。它似乎仅在专门加载标记时发生(即,子选择被触发)。如果切换到join或select fetch策略,则不会删除关系,但这会导致执行N+1查询

我最好的猜测是NHibernate认为这些标签是孤立的,但我们还没有对这些集合设置任何级联。而且,据我所知,设置级联没有任何效果

在NHibernate 2.x和NHibernate.Linq下,这个过程非常有效。我们在迁移到NHibernate 3.x之前没有发现删除的问题,它内置了LINQ支持。我不确定这会有什么不同,但不管它值多少钱,我们使用的是带有身份密钥的SQL Server

有什么想法吗?我起初认为我做了一些愚蠢的事情,但我基本上尝试了映射的每一种排列,我们似乎无法消除这个问题


编辑:另一条有趣的信息。如果在关闭会话之前调用
session.IsDirty()
,则不会出现问题。我怀疑这是因为在刷新之间并没有持久保存集合更改,但我无法很好地破译NHibernate的源代码,因此无法确定。

您能否为我们提供一些线索,了解您在这里试图实现的目标?我从未在多对多上尝试过指定的获取,但我认为这与某种显式的cascade=all for a many to many有关。

您是否在实体映射中设置了:cascade.None()这将停止删除实体以外的任何内容


这可能会有帮助:

你能为故事和标签属性发布getter吗?@Jakub-getter只是自动属性,类型为
ICollection