Entity Framework Il existe déjà un DataReader ouvert associé à cette command qui doit être fermé en premier

Je me bats avec l'erreur ci-dessus. J'ai trouvé différentes réponses ici (stack overflow), mais aucune d'entre elles ne résout mon problème lié à l'erreur.

J'active simplement MARS dans ma ConnectionSsortingng mais sans succès.

J'ai un produit de class

public class Product { public Product() { this.Additives = new HashSet<Additive>(); } public int Id { get; set; } public ssortingng Name { get; set; } // refrigerante public ssortingng CommercialName { get; set; } // nome popular, ex: fanta laranja public ssortingng Brand { get; set; } // marca, ex: Coca-cola public ssortingng 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; } } 

}

et Additif de class représentant les additifs dans les produits

 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 ssortingng Key { get; set; } // codigo ex: E130 public ssortingng NamePT { get; set; } // nome ex: Acido ascorbico (Vitamina C) em portugues public ssortingng NameEN { get; set; } // nome ex: Acido ascorbico (Vitamina C) em inglês public ssortingng 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;} } } 

J'écris un code pour implémenter une méthode sur ProductRepository afin d'get des produits avec un additif spécifique.

 public ICollection<Product> GetProductsByAdditive(ssortingng 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 } 

L'erreur se produit exactement après la première boucle foreach, sur cette instruction:

 var additives = p.Additives; 

PS: J'utilise EF 6. Je suis empilé! S'il vous plaît aider!

Heres mes connections

 <?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> <connectionSsortingngs> <add name="EatHalal" providerName="System.Data.SqlClient" connectionSsortingng="Server=192.168.1.150;Database=EatHalal;User Id=user;Password=password;MultipleActiveResultSets=true;" /> </connectionSsortingngs> </configuration> 

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

votre code échoue parce que vous êtes paresseux charge les additifs tout en itérant sur les produits …

mais l'itération elle-même est absurde … si vous voulez chercher quelque chose dans la database, laissez la database faire son travail en lui donnant quelque chose à chercher, au lieu de lui donner tout ce que vous voulez. ..

Imaginez s'il y aurait quelques centaines de millions de produits dans votre table …

vous chargerez TOUS les produits et les traverserez pendant des lustres …

regardez LINQ

regardez .Where ()

regardez .Select ()

se familiariser avec les expressions lambda

Vous pouvez essayer comme indiqué ci-dessous.

Remarque: Vous devez d'abord importer datatables, puis effectuer le mappage et vous ne rencontrerez pas ce problème.

Raison: lorsque vous parcourez le résultat de la requête ( IQueryable ) et que vous lancez un lazy loading pour l'entité chargée à l'intérieur de l'itération. En d'autres termes, plusieurs commands d'extraction de données sont exécutées sur une seule connection.

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

Pour être précis, iterer via un IQueryable utilise un lecteur de données ouvert (vous pouvez donc arrêter d'itérer sans lire tous les produits de la database). Si vous chargez des additifs de chargement, EF utilise la même connection pour récupérer les additifs de sorte que l'erreur ADO.

Dans ce cas, vous pouvez lire tous les produits en utilisant un ToList comme suggéré dans une autre réponse ou utiliser Include(p => p.Additives) pour des données de chargement impatientes.

Dans votre cas spécifique, la meilleure chose à faire est de filterr les produits par additif afin que votre fonction soit

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

Vous devriez être en mesure de résoudre ce problème en chargeant avec impatience les Additives en même time que vous chargez les Products , au lieu de countr sur un chargement paresseux.

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

Cela récupérera des Additives dans le cadre de la même requête qui charge les Products . Il sera également plus efficace, car il ne charge que les Additives liés aux Products vous renvoyez. Bien que vous chargiez TOUS les Products en ce moment, ce n'est peut-être pas une amélioration énorme pour cette requête exacte.