2010-11-08 4 views
0

J'ai vu pas mal de façons de faire fonctionner LINQ dynamique pour le .GroupBy, mais tous ceux que je vois semblent s'attendre à une entité codée en dur. Je veux reproduire ce qui suit LINQ comme dynamique:Utilisation de LINQ dynamique pour GroupBy sur DataTable

//need dynamic LINQ for this 
var groupedRows = rows.GroupBy(z => new { make = z["make"], model = z["model"] }) 
         .Select(x => x.Key); 

Je voudrais être en mesure de faire exactement cela, ce qui rend l'ensemble de la fonction d'une chaîne:

var groupedRows = rows.GroupBy(z => "new { make = z[\"make\"], model = z[\"model\"] }") 

Je me rends compte que si elle était seulement une entité régulière, je pouvais le faire

mylist.GroupBy(z => new { make = z.make, model = z.model }).Select(x => x.Key); 

Si j'avais cette entité régulière, je pourrais utiliser Mitsu's dynamic GroupByMany. J'essaye d'obtenir ceci pour fonctionner avec un datatable régulier (pas fortement typé). Des idées?

Répondre

0

Ok, j'ai été capable de travailler avec le code de compilation et de réflexion au moment de l'exécution en utilisant le compilateur mono un service (MCS). En utilisant la question Injecting a variable into the Mono.CSharp.Evaluator (runtime compiling a LINQ query from string), je suis venu avec la solution suivante (n ° 2 dans la réponse à cette question):

DataTable dt = GetData(); 
     var dataRows = dt.AsEnumerable(); 

     //Initializing the evaluator 
     Evaluator.Init(new string[0]); 
      Evaluator.ReferenceAssembly(Assembly.GetAssembly(typeof(DataRow))); 
      Evaluator.ReferenceAssembly(Assembly.GetExecutingAssembly()); 

     Evaluator.Run(@"using System; 
      using System.Linq; 
      using System.Collections.Generic; 
      using System.Data; 
      using MyNamespace;"); 

     var func = (Func<DataRow, object>)Evaluator.Evaluate(@"new Func<DataRow,object>(z => new 
       { 
        make = z[""make""], 
        model = z[""model""] 
       });"); 

     dataRows.GroupBy(func).Select(x => x.Key); 

donc qui compile la fonction lors de l'exécution, puis appelle la fonction dans la GroupBy pour chaque ligne. Quand j'avais besoin de la valeur de make ou de model, je devais ensuite utiliser la réflexion pour arriver à cette valeur grâce à ma méthode d'extension GetPropertyValue.

Je n'arrive toujours pas à faire fonctionner LINQ dans le MCS, même après avoir suivi la question Mono Compiler as a Service (MCS), mais en l'utilisant simplement pour créer la fonction, j'ai fait ce que j'avais besoin de faire.

0

Je ne pense pas que ce soit possible; ceci suggère que vous voulez que le compilateur C# compile votre chaîne à l'exécution =)
Le problème n'est pas les indexeurs "make" et "model", ce sont les membres des nouvelles instances que vous renvoyez; ceux-ci ne peuvent être représentés textuellement que par Reflection, mais je sais que LINQ-to-Entities ne supporte pas ses fonctions, mais je ne suis pas sûr que LINQ le fera normalement.
Seriez-vous d'accord avec une solution de réflexion?
Je veux savoir si vous êtes d'accord avant de passer deux heures à essayer de le faire =

+0

Je serais absolument d'accord avec une solution de réflexion. Le problème, c'est évidemment la performance, et cela dépend de ce qui est nécessaire. Si c'était nécessaire sur chaque colonne de chaque rangée, je soupçonnerais que ce serait un problème. Si juste une fois, pas de problème. Je crois que nous atteindrons un maximum d'environ 500 lignes. – DougJones

+0

Pouvez-vous me donner un exemple de 'lignes'? Est-ce juste un tas d'objets similaires? – BeemerGuy

+0

C'est un datatable. <% DataTable dt = GetData(); var rows = dt.AsEnumerable(); %> – DougJones