Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/79.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
C# NHibernate ToList(),然后执行导致多个查询的查询_C#_Sql_Nhibernate - Fatal编程技术网

C# NHibernate ToList(),然后执行导致多个查询的查询

C# NHibernate ToList(),然后执行导致多个查询的查询,c#,sql,nhibernate,C#,Sql,Nhibernate,我有一个项目列表(不会改变),所以使用NHibernate查询并转换为内存中的列表,如下所示 foreach(Item item in AllItems) { var itemName = item.Name; var itemUserCount = item.Users.Count; } List myItems=\u repository.All().ToList() 稍后,当用户进行搜索并单击下面的搜索按钮时 myItems.Where(item=>item.Name==

我有一个项目列表(不会改变),所以使用NHibernate查询并转换为内存中的列表,如下所示

foreach(Item item in AllItems)
{

   var itemName = item.Name;
   var itemUserCount = item.Users.Count;

}
List myItems=\u repository.All().ToList()

稍后,当用户进行搜索并单击下面的搜索按钮时

myItems.Where(item=>item.Name==searchTerm)

我看到第一个代码导致下面的查询(等价的不精确)

从项目中选择*

然后,第二个代码对数据库造成另一次命中,即使它位于内存对象中

从Name='Stackoverflow'的项目中选择*

如何停止不必要的查询?

每个项目可以属于多个用户,因此项目具有如下映射

foreach(Item item in AllItems)
{

   var itemName = item.Name;
   var itemUserCount = item.Users.Count;

}
HasMany(x=>x.Users).KeyColumn(“UserId”)

在一个显示有项目的用户数量的页面中,我有如下代码

foreach(Item item in AllItems)
{

   var itemName = item.Name;
   var itemUserCount = item.Users.Count;

}
上面是对用户表的N个查询,即如果Items count=100,则对用户表执行100个查询以获得计数

How do i optimize the above mapping to work efficiently?
资源:


您最好只提取所需的数据(使用LINQ提供程序):

这可能会创建一个
左连接
,但您需要急切地获取可能需要的所有其他实体

有一种简单的方法可以确定您是否存在N+1问题:在提取数据后立即处理会话。如果您在任何地方访问一个非急切获取的相关实体,您将得到一个异常,这使得调试此类情况变得更加容易:

IList<Item> list;
using(var session = sessionFactory.OpenSession())
{
    list = session.QueryOver<Item>().Fetch(x => x.User).Eager.List();
}
var otherStuff = list.Select(x => x.OtherItem.Price).ToList(); // Boom, exception! OtherItem was not eagerly fetched.
IList列表;
使用(var session=sessionFactory.OpenSession())
{
list=session.QueryOver().Fetch(x=>x.User.Eager.list();
}
var otherStuff=list.Select(x=>x.OtherItem.Price).ToList();//轰,例外!其他物品并没有被急切地取走。

您最好只提取所需的数据(使用LINQ提供程序):

这可能会创建一个
左连接
,但您需要急切地获取可能需要的所有其他实体

有一种简单的方法可以确定您是否存在N+1问题:在提取数据后立即处理会话。如果您在任何地方访问一个非急切获取的相关实体,您将得到一个异常,这使得调试此类情况变得更加容易:

IList<Item> list;
using(var session = sessionFactory.OpenSession())
{
    list = session.QueryOver<Item>().Fetch(x => x.User).Eager.List();
}
var otherStuff = list.Select(x => x.OtherItem.Price).ToList(); // Boom, exception! OtherItem was not eagerly fetched.
IList列表;
使用(var session=sessionFactory.OpenSession())
{
list=session.QueryOver().Fetch(x=>x.User.Eager.list();
}
var otherStuff=list.Select(x=>x.OtherItem.Price).ToList();//轰,例外!其他物品并没有被急切地取走。

我认为是一个问题,即用户集合填充,分别针对每个项目进行。解决N+1问题的有效方法是采用批量加载。在文档中可以找到非常清楚的解释

问题/答案有点陈旧,因此在您的案例中使用的语法应该是:

HasMany(x => x.Users)
    .KeyColumn("UserId")
    .BatchSize(20) // here we go
    ;

这将大大减少查询量。因为一次会加载很多用户。

我认为一个问题是,每个项目的用户集合填充是分别完成的。解决N+1问题的有效方法是采用批量加载。在文档中可以找到非常清楚的解释

问题/答案有点陈旧,因此在您的案例中使用的语法应该是:

HasMany(x => x.Users)
    .KeyColumn("UserId")
    .BatchSize(20) // here we go
    ;

这将大大减少查询量。因为会同时加载大量用户。

选择N+1
问题。您应该急切地加载
用户
,或者,更好的是,首先只提取您真正需要的数据。@我如何急切地加载用户。我是NHibernate映射的初学者。我没有。LazyLoad()
而且它不会造成任何不同
选择N+1
问题。您应该急切地加载
用户
,或者,更好的是,首先只提取您真正需要的数据。@我如何急切地加载用户。我是NHibernate映射的初学者。我没有使用.LazyLoad()
,并且它不会产生不同的问题1-从存储库返回的项目是
IEnumerable
,它被转换为
List
。那么,当所有记录都在内存中时,为什么还要发出另一个查询呢。到目前为止,我一直认为,当
IQuerable时,当转换为list时,IEnumerable与数据没有任何关联source@Deeptechtons返回实体时,则(通常)您返回的代理仍然可以在会话范围内调用会话。问题1-从存储库返回的项目是
IEnumerable
,它被转换为
List
。那么,当所有记录都在内存中时,为什么还要发出另一个查询呢。到目前为止,我一直认为,当
IQuerable时,当转换为list时,IEnumerable与数据没有任何关联source@Deeptechtons当您返回实体时,那么(通常)您返回的代理仍然可以在会话范围内调用会话。