开发者

Using dynamic LINQ for GroupBy on DataTable

I have seen quite a few ways to get dynamic LINQ to work for the .GroupBy, but every one that I see seems to expect a hard coded entity. I want to reproduce the following as dynamic LINQ:

//need dynamic LINQ for this
var groupedRows = rows.GroupBy(z => new { make = z["make"], model = z["model"] })
                      .Select开发者_运维百科(x => x.Key);

I'd like to be able to just do this, making the entire function a string:

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

I realize that if it were only a regular entity, I could do this

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

If I had that regular entity, I could use Mitsu's dynamic GroupByMany.

I am trying to get this to work with a regular datatable (not strongly typed). Any ideas?


I don't think that's possible; this suggests you want the C# compiler to compile your string at runtime =)
The problem isn't the "make" and "model" indexers, it's the members in the new instances you're returning; those can only be textually represented by Reflection, but I know LINQ-to-Entities doesn't support its functions, not sure if normal LINQ will.
Would you be ok with a Reflection solution?
I wanna know if you're ok with it before I spend two hours trying to make it work =)


Ok, I was able to get this working with both reflection and compiling code at runtime using the Mono Compiler as a Service (MCS). Utilizing the question Injecting a variable into the Mono.CSharp.Evaluator (runtime compiling a LINQ query from string), I came up with the following solution (#2 in the answer to that 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);

So that compiles the function at runtime, then calls the function in the GroupBy for each row. When I needed the value of make or model, I then needed to use reflection to get to that value through my GetPropertyValue extension method.

I still can't get LINQ working within the MCS, even after following the Mono Compiler as a Service (MCS) question, but just using it to creating the function did what I needed it to do.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜