Entity Framework 已经有一个与此命令关联的打开的 DataReader,必须先将其关闭

Entity Framework There is already an open DataReader associated with this Command which must be closed first

我正在为上述错误而苦恼。我在这里找到了不同的答案(堆栈溢出),但是 none 解决了我与错误相关的问题。

我只是在我的 ConnectionString 中启用了 MARS,但没有成功。

我有一个 class 产品

public class Product
{
    public Product()
    {
        this.Additives = new HashSet<Additive>();
    }

    public int Id { get; set; }
    public string Name { get; set; } // refrigerante
    public string CommercialName { get; set; } // nome popular, ex: fanta laranja
    public string Brand { get; set; } // marca, ex: Coca-cola
    public string Details { get; set; } // composicao, ingredientes
    public HalalState HalalState { get; set; } // estado: halal, haram ou desconhecido
    public DateTime? LastUpdate { get; set; } // date e hora do registo

    public virtual ICollection<Additive> Additives { get; set; } // aditivos
    public int ProviderID { get; set; }
}

}

and classAdditive代表产品中的添加剂

using System;
using System.Collections.Generic;

namespace Teknowhow.EatHalal.Core.Models
{
    public class Additive
    {
        public Additive()
        {
            this.Products = new HashSet<Product>();
        }

        public int Id { get; set; }
        public string Key { get; set; } // codigo ex: E130
        public string NamePT { get; set; } // nome ex: Acido ascorbico (Vitamina C) em portugues
        public string NameEN { get; set; } // nome ex: Acido ascorbico (Vitamina C) em inglês
        public string Details { get; set; } // detalhes sobre o aditivo, incluindo.
        public HalalState HalalState; // estado: halal, haram ou desconhecido
        public DateTime? LastUpdate { get; set; } // date e hora do registo

        public virtual ICollection<Product> Products { get; set;}
    }
}

我正在编写代码来实现 ProductRepository 上的方法,以便获得具有特定添加剂的产品。

public ICollection<Product> GetProductsByAdditive(string key)
{
    var products = context.Products;
    var productsAdditives = new List<Product>();

     foreach (var p in products)
     {
         var additives = p.Additives;

         foreach (var a in additives)
         {
             if (a.Key.Equals(key))
                productsAdditives.Add(p);   

         }
    }

    return productsAdditives.ToList();
    //TODO: um Metodo úinico que permite pesquisa por nome em PT e EN e codigo 

}

错误恰好发生在第一个 foreach 循环之后,在这个语句中:

var additives = p.Additives;

PS:我正在使用 EF 6。 我堆积了!请帮忙!

这是我的联系人

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
        <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    </configSections>
    <connectionStrings>
    <add name="EatHalal" 
         providerName="System.Data.SqlClient" 
         connectionString="Server=192.168.1.150;Database=EatHalal;User Id=user;Password=password;MultipleActiveResultSets=true;"
             />
  </connectionStrings>
</configuration>
context.Products.Where(x=>x.Additives.Any(y=>y.Key==key)).ToList();

您的代码失败是因为您在迭代产品时延迟加载添加剂...

但是迭代本身是无意义的......如果你想在数据库中搜索一些东西,让数据库通过给它一些东西来搜索来完成它的工作,而不是告诉它给你所有的东西然后排序出你想要的...

想象一下,如果您的 table 中有几亿种产品 ...

您会加载所有产品并浏览它们很长时间...

看看 LINQ

看看 .Where()

看看.Select()

熟悉 lambda 表达式

您可以尝试下图

注意:你必须先带数据再做映射才不会出现这个问题

原因: 当您遍历查询结果 (IQueryable) 并且您将触发 lazy loading 以加载 [=23= 中的实体] 换句话说,在单个连接上执行了多个数据检索命令。

         foreach (var p in products.ToList())
            {
                var additives = p.Additives.ToList();

                foreach (var a in additives)
                {
                    if (a.Key.Equals(key))
                    {
                        productsAdditives.Add(p);   
                    }   
                }
            }

准确地说,通过 IQueryable 进行迭代使用了一个开放的数据读取器(因此您可以停止迭代而无需从数据库中读取所有产品)。如果您延迟加载添加剂,EF 会使用相同的连接来检索添加剂,因此会出现 ADO 错误。

在这种情况下,您可以像另一个答案中建议的那样使用 ToList 读取所有产品,或者使用 Include(p => p.Additives) 预先加载数据。

在您的具体情况下,最好的办法是按添加剂过滤产品,因此您的功能应该是

public ICollection<Product> GetProductsByAdditive(string key)
{
    return context.Products.Where(p => p.Additives.Select(a => a.Key).Contains(key)).ToList();
}

您应该可以通过在加载 Products 的同时预先加载 Additives 来解决此问题,而不是依赖延迟加载。

var products = context.Products.Include(p => p.Additives);

这将获取 Additives 作为加载 Products 的同一查询的一部分。它还会更有效率,因为它只会加载链接到 Products 你 return 的 Additives。虽然您目前正在加载所有 Products,但对于这个确切的查询来说,这可能不是一个巨大的改进。