Partager via


GQ08 IV: Linq to Sql bug ?

Un peu de Linq to Sql !

Le fonctionnel est simple, j'aimerais depuis toutes les catégories récupérer une liste d'éléments regroupant le nom de la catégorie ainsi qu'un dictionnaire des produits appartenants à cette catégorie. Ceci afin de pouvoir retrouver rapidement un produit appartenant à une catégorie.

Le code suivant est syntaxiquement correct, il compile même !

Pourtant son exécution est impossible. Quelle est l'erreur ?

 var db = new NorthwindDataContext();
var q =
    from c in db.Categories
    select new { Name = c.CategoryName,
        Products = c.Products.ToDictionary(cat => cat.CategoryID) };

foreach (var c in q)
{
    if (c.Products.ContainsKey(123))
        Console.WriteLine(c.Name + " contient le produit d'id 123");
}

PS: c'est vendredi !! Prenez le temps de répondre et ne laissez pas tout à Matthieu ! :p

Comments

  • Anonymous
    August 08, 2008
    PingBack from http://blog.a-foton.ru/2008/08/gq08-iv-linq-to-sql-bug/

  • Anonymous
    August 08, 2008
    t'es sûr que tu ne t'es pas trompé ? Ton dico, sa clé ça va être le CategoryID. Donc le WriteLine ne me parait pas bon !

  • Anonymous
    August 08, 2008
    Pour ce qui est de la réponse, je pense qu'il faut utiliser un AsEnumerable()

  • Anonymous
    August 08, 2008
    Pour ma part, j'aurais fait ça : var db = new DataClasses1DataContext(); var productsDico =    db.Categories.AsEnumerable().ToDictionary(cat => cat.CategoryID, cat => cat.Products); var q = db.Categories; foreach (var c in q) {    if (productsDico[c.CategoryID].Any(p=>p.ProductID == 123))        Console.WriteLine(c.CategoryName + " contient le produit d'id 123"); } mais je ne pense pas que ce soit ce que tu veux.

  • Anonymous
    August 08, 2008
    ou plutôt ça (au cas où il y est des catégories sans products : var db = new DataClasses1DataContext(); var productsDico =    db.Categories.AsEnumerable().ToDictionary(cat => cat.CategoryID, cat => cat.Products); foreach (var c in db.Categories) {    if (productsDico.ContainsKey(c.CategoryID) && productsDico[c.CategoryID].Any(p=>p.ProductID == 123))        Console.WriteLine(c.CategoryName + " contient le produit d'id 123"); }

  • Anonymous
    August 08, 2008
    Mitsu, continu stp a poster tes quizz pendant que Matthieu déjeune, ce nous laisse un peu plus de temps pour réflechir avant la réponse :)

  • Anonymous
    August 08, 2008
    J'ai trouvé la solution ! J'ai activé la modération et je limiterai Matthieu à une seule réponse :)

  • Anonymous
    August 08, 2008
    Mieux ! tu me file les réponses discret et je te ré-invite à prendre une bierre :)

  • Anonymous
    August 08, 2008
    Mais euh ! Et puis si ton énoncé était plus compréhensible, je n'aurais pas eu besoin de plusieurs réponses :p A propos de réponse, j'ai pas encore vu la tienne (http://blogs.codes-sources.com/matthieu/archive/2008/08/08/comme-mitsu.aspx). Tu le dis si c'est trop compliqué :p Plus sérieusement, c'est ça que tu voulais ?

  • Anonymous
    August 09, 2008
    The comment has been removed

  • Anonymous
    August 09, 2008
    Ce que j'attendais était donc bien: var q =    from c in db.Categories    select c; var q2 =    from c in q.AsEnumerable()    select new { Name = c.CategoryName,        Products = c.Products.ToDictionary(cat => cat.CategoryID) }; q est bien une requête Linq to Sql car la source 'db.Categories' est bien une Table Linq to Sql. Linq to Sql tente donc de convertir l'intégralité de l'expression en SQL. Evidemment le select avec le dictionary n'est pas reconnu à l'exécution et la requête Linq échoue. La question porte donc bien sur l'isolation de la requête. Si vous voulez enchainer des requêtes Linq entre Sql, Xml, objets ou d'autres provider, pensez bien à isoler les requêtes. Pour ceci, deux solutions. Faire un q.ToList() afin de terminer la première requête et démarrer la seconde sur la liste résultante ou utiliser .AsEnumerable() qui 'cassera' la première expression et vous permettra d'être sûr que je reste définit une reqûete Linq to Object.

  • Anonymous
    August 10, 2008
    "var q =   from c in db.Categories   select c;" Autant utiliser directement db.Categories.

  • Anonymous
    August 11, 2008
    Bien sûr Matthieu. Mais là ça permet à tout le monde de bien visualiser une requête simple que l'on peut facilement enrichire d'un 'where', un 'order by' ou autre. Tu comprends ? :)

  • Anonymous
    August 12, 2008
    C'est pas du jeu ça... je viens de recevoir le flux rss que maintenant ! Qqun sait-il pourquoi il y a tant de décalage ? Ou bien c'est une astuce de Matthieu pour éliminer la concurrence ? :-)