查询的结果不能多​​次枚举

Hal*_*yon 67 c# linq asp.net entity-framework entity-framework-4

我正在使用实体框架(ef)并收到以下错误:

"查询的结果不能多​​次枚举."

我有一个包含ef数据上下文的存储库类.然后我有一个控制器类(不要与MVC控制器混淆),它包含一个存储库实例.到目前为止一直这么好......我在控制器上有一个搜索方法,它应该返回一个数组RadComboBoxItemData,用于填充Telerik RadComboBox控件.

public RadComboBoxItemData[] Search(int id, string searchText)
{
    var query = context.Search(id, searchText);
    List<RadComboBoxItemData> result = new List<RadComboBoxItemData>();
    foreach (var item in query)
    {
        RadComboBoxItemData itemData = new RadComboBoxItemData();
        itemData.Text = ""; // assign some text here..;
        itemData.Value = ""; /*assign some value here..*/
        result.Add(itemData);
    }

    return result.ToArray();
}
Run Code Online (Sandbox Code Playgroud)

当我调试我的代码时,我可以进入foreach循环,但后来我得到一个错误说:

System.Data.Entity.dll中出现"System.InvalidOperationException"类型的异常,但未在用户代码中处理

附加信息:查询结果不能多​​次枚举.

我的实体使用现有存储过程的函数导入.

// EF repository method calling the function imported method on the data context.
public IEnumerable<SearchItem> Search(int id, string searchText)
{
    return this.entityContext.Search(id, searchText);
}
Run Code Online (Sandbox Code Playgroud)

函数import Search调用存储的precedure来返回一个集合SearchItem.

我有一种感觉,foreach循环不能因为ef的某些东西而迭代.

Yak*_*ych 138

尝试通过调用显式枚举结果ToList().

更改

foreach (var item in query)
Run Code Online (Sandbox Code Playgroud)

foreach (var item in query.ToList())
Run Code Online (Sandbox Code Playgroud)

  • `.ToList()`的工作原理是当你使用*IEnumerable*时,集合以**lazy**方式迭代.在这种情况下,每次*foreach*循环获取一个项目时,查询将从您的数据库或您正在使用的任何内容中检索该项目,如果您想再次迭代它将无法重做查询.当你使用`.ToList()`时,*IEnumerable*中的所有项都被处理并保存为列表.然后,您可以根据需要多次使用创建的列表. (14认同)
  • 进一步澄清.问题的根源是存储过程仅返回结果集.这意味着一旦你到达终点,你必须重做查询以回到开始.但是,列表将结果集转换为List数据结构,可以根据需要多次枚举. (8认同)
  • 那很有效!你能解释一下它的工作原理吗? (5认同)
  • @Halcyon它的工作原理是因为使用`ToList`你从这个列表中的数据库中检索所有结果,从现在起linq方法不能在数据库上工作.这可能是一个严重的性能问题,具体取决于您拥有的数据量以及您将使用的数据. (5认同)
  • @BrunoLM - 在这种情况下,OP已经遍历所有查询结果.如果需要对数据库执行更多"linq方法",他可以继续使用`query`变量.我不仅没有看到解决方案的问题,而且它是解决OP问题的最佳方法.关注downvote? (4认同)

hos*_*ily 7

尝试替换它

var query = context.Search(id, searchText);
Run Code Online (Sandbox Code Playgroud)

var query = context.Search(id, searchText).tolist();
Run Code Online (Sandbox Code Playgroud)

一切都会好起来的.