14

我正在使用 LINQ to SQL 在 Sql server 2008 中获取 FullTextSearch 存储过程的搜索结果。我将过程从服务器资源管理器拖到设计器中,并获得了使用适当的返回类型和参数创建的方法。现在的问题是,我需要获取调用此方法的结果的计数,因此使用我的存储库方法(它将调用 Sproc 方法并将结果作为 IQueryable 返回)我进行了以下调用。

var result = repository.FullTextSearch(searchText);
        int resultsCount = result.Count();
        var ret = result.Skip((pageNumber - 1) * PageSize).Take(PageSize).ToList();

这段代码每次我尝试运行它时都会生成一个 InvalidOperationException,异常说(是的,你猜对了!)“查询结果不能被枚举多次。”

为 Sproc 生成的方法返回 ISingleResult,它应该是 OK AFAIK。我需要在我的视图上支持分页,所以我需要知道总页数,只有在我可以获得所有项目的计数时,这(再次是 AFAIK)才有可能。

伙计们,我在这里错过了什么?

4

4 回答 4

17

您可以做的是ToList()repository.FullTextSearch(searchText). 这样,从服务器检索结果,之后您可以随心所欲地使用它们(因为它们现在已加载到内存中)。

您现在要做的是两次运行相同的 SQL 查询,这是相当低效的。

于 2009-09-01T08:43:06.993 回答
14

由于这是执行一个存储过程,所以你所有可爱的Skip/Take基本上都是多余的......它别无选择,只能将所有数据带回来(存储过程调用是不可组合的)。它唯一能做的就是不为其中一些对象具体化。

我想知道更好的方法是重构代码以进行两次调用:

int result = repository.FullTextSearchCount(searchText);
var result = repository.FullTextSearch(searchText, skip, take); // or similar

即使分页参数成为 SPROC 的一部分(以及使用ROW_NUMBER()/OVER(...)或表变量、临时表等在数据库中进行过滤) - 或者与OUTPUTsproc 中的参数类似的东西:

int? count = null;
var result = repository.FullTextSearch(searchText, skip, take, ref count);

(我似乎记得OUTPUT变成了ref,因为 TSQLOUTPUT真的是输入+输出)

于 2009-09-01T08:45:45.597 回答
5

使用ToList()可以帮助避免这个问题。

var result = repository.FullTextSearch(searchText).ToList();
于 2011-11-03T09:13:16.583 回答
1

我建议如果您需要计数,请先执行结果。然后从列表本身运行计数,因为您在结果执行中不使用 resultsCount 。

var result = repository.FullTextSearch(searchText);
var ret = result.Skip((pageNumber - 1) * PageSize).Take(PageSize).ToList();
int resultsCount = ret.Count();
于 2009-09-01T08:53:49.920 回答