【问题标题】:The result of a query cannot be enumerated more than once一个查询的结果不能被枚举多次
【发布时间】:2011-04-19 22:35:55
【问题描述】:

我正在使用实体框架 (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.InvalidOperationException' 发生在 System.Data.Entity.dll 但 未在用户代码中处理

附加信息:结果 一个查询不能枚举超过 一次。

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

// 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);
}

函数 import Search 调用存储的过程以返回 SearchItem 的集合。

我感觉 foreach 循环由于 ef 的某些问题而无法迭代。

【问题讨论】:

  • 你缺少一个 .ToList(),我只是看不到在哪里...我去喝杯咖啡再看看

标签: c# asp.net linq entity-framework entity-framework-4


【解决方案1】:

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

改变

foreach (var item in query)

foreach (var item in query.ToList())

【讨论】:

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

尝试替换这个

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

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

一切都会好起来的。

【讨论】:

  • tolist() 使实体免费,如果您不使用 tolist,则预计该实体未发布,您将对其进行处理
【解决方案3】:

如果你遇到这种类型的错误,那么我建议你习惯于像往常一样存储 proc 数据列表,然后绑定其他控件,因为我也遇到了这个错误,所以我这样解决了 例如:-

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

这样试试

【讨论】:

    猜你喜欢
    • 2011-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多