SQL Server 实体框架已存在与此命令关联的打开的DataReader,必须先关闭该DataReader

5jdjgkvh  于 2023-01-12  发布在  其他
关注(0)|答案(5)|浏览(127)

我正在为上面的错误而挣扎。我在这里找到了不同的答案(堆栈溢出),但是没有一个能解决我的问题。
我只是在ConnectionString中启用了MARS,但没有成功。
我有一个类产品

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

}
添加剂类表示产品中的添加剂

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;

附言:我用的是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>
rqenqsqc

rqenqsqc1#

您可以尝试如下所示。

**注意:**您必须先获取数据,然后再进行Map,这样就不会出现此问题。
**原因:**当您迭代查询结果(IQueryable)时,您将在迭代中为加载的实体触发lazy loading。换句话说,在单个连接上执行了多个数据检索命令。

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

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

yuvru6vn2#

context.Products.Where(x=>x.Additives.Any(y=>y.Key==key)).ToList();

您的代码失败是因为您在迭代产品时延迟加载了添加剂...
但是迭代本身就是无稽之谈...如果你想在数据库中搜索一些东西,让数据库通过给它一些东西来搜索来完成它的工作,而不是告诉它给予你一切,然后整理出你想要的东西...
想象一下如果你的表中有几亿个产品...
你会加载所有的产品,并通过他们的年龄。
看看LINQ
看。哪里()
查看。选择()
熟悉lambda表达式

omqzjyyz

omqzjyyz3#

准确地说,迭代IQueryable使用一个开放的datareader(这样你就可以停止迭代,而不用从数据库中阅读所有的产品)。如果你延迟加载Additives,EF使用相同的连接来检索Additives,所以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();
}
3wabscal

3wabscal4#

您应该能够通过在加载Products的同时急切地加载Additives来解决这个问题,而不是依赖于延迟加载。

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

这将获取Additives作为加载Products的同一个查询的一部分。它也将更有效,因为它只加载链接到您返回的ProductsAdditives。虽然您现在加载的是所有Products,但对于这个确切的查询来说,它可能不是一个巨大的改进。

prdp8dxp

prdp8dxp5#

只需在连接字符串中添加MultipleActiveResultSets=True

相关问题