查询结果不能被多次枚举


69

我正在使用实体框架(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();
}

当我调试代码时,我可以进入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);
}

函数importSearch调用存储的过程以返回的集合SearchItem

我有一种感觉,由于ef的影响,foreach循环无法迭代。


4
您缺少.ToList(),我只是看不到哪里...我要去喝咖啡再看一眼
Smudge202

Answers:


144

尝试通过调用明确枚举结果ToList()

更改

foreach (var item in query)

foreach (var item in query.ToList())

5
@Halcyon之所以有效,是因为使用ToList此方法从此列表中的数据库中检索所有结果,从现在开始,linq方法将无法在数据库上工作。这可能是一个严重的性能问题,具体取决于您拥有的数据量以及如何处理。
BrunoLM 2011年

4
@BrunoLM-在这种情况下,OP已经遍历所有查询结果。如果需要对数据库执行更多的“ linq方法”,他可以继续使用该query变量。我不仅看不到解决方案有问题,而且还是解决OP问题的最佳方法。关心解释下票吗?
Yakimych

14
.ToList()起作用的原因是,当您使用IEnumerable时,集合以惰性方式进行迭代。在这种情况下,每次foreach循环获取一个项目时,查询都会从您的数据库或您正在使用的任何内容中检索该项目,如果您想再次进行迭代,将无法重做查询。使用时.ToList(),将处理IEnumerable中的所有项目并将其保存为列表。然后,您可以根据需要多次使用创建的列表。
Vicro 2014年

8
进一步澄清。问题的根源在于存储过程仅返回结果集。这意味着一旦到达末尾,就必须重做查询以重新开始。但是,to list会将结果集转换为List数据结构,可以根据需要多次枚举。
Ageis

8

尝试更换它

var query = context.Search(id, searchText);

var query = context.Search(id, searchText).tolist();

一切都会很好。


tolist()使实体免费,如果您不使用tolist,则表示实体未发布,您将对其进行工作
hosam hemaily

-5

如果您遇到这种类型的错误,那么我建议您以前将proc数据存储为通常的列表,然后绑定其他控件,因为我也遇到了此错误,所以我像这样解决了它:

repeater.DataSource = data.SPBinsReport().Tolist();
repeater.DataBind();

这样尝试

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.