dynamic linq expression using select in .NET

.net c# dynamic-linq lambda linq

Question

I want to dynamically add .Select statements, but the compiler will only allow me to build these statements inside the current scope. I am aware of linqkit, which could be a solution, but i dont want to add any external functionallity. How do i avoid this code duplication which i have now:

 if (request.Equals("some text"))
        {
            var filter = commonFilter.GroupBy(x => new
                {
                    x.Timestamp.Year,
                    x.Timestamp.Month,
                })
                .Select(g => new
                {
                    Year = g.Key.Year,
                    Month = g.Key.Month,
                    TotErr = g.Count(),

                    column1 = g.Sum(o => o.Process.Contains("something") ? 1 : 0),
                    column2= g.Sum(o => o.Process.Contains(".something1") ? 1 : 0),
                    column3= g.Sum(o => o.Process.Contains(".something2") ? 1 : 0),
                    column4= g.Sum(o => o.Process.Contains("something3") ? 1 : 0),
                    column5= g.Sum(o => o.Process.Contains(".something4") ? 1 : 0),
                    column6 = g.Sum(o => o.Process.Contains(".something5") ? 1 : 0),
                    column7= g.Sum(o => o.Process.Contains(".something6") ? 1 : 0),
                    column8= g.Sum(o => o.Process.Contains(".something7") ? 1 : 0),
                    column9= g.Sum(o => o.Process.Contains(".something8") ? 1 : 0),

                    NumOrgs = g.Select(l => l.OrganizationId).Distinct().Count(),
                    NumUsers = g.Select(l => l.UserId).Distinct().Count(),

                });

            return filter.AsPa......;//not important right now
        }
        //Same thing again but slightly different
        else if (request.Equals("some other text"))
        {
            var filter = commonFilter.GroupBy(x => new
                {
                    x.Timestamp.Year,
                    x.Timestamp.Month,
                    x.Timestamp.Day
                })
                .Select(g => new
                {
                    Year = g.Key.Year,
                    Month = g.Key.Month,
                    Day= g.Key.Day,
                    TotErr = g.Count(),

                    column1 = g.Sum(o => o.Process.Contains("something") ? 1 : 0),
                    column2= g.Sum(o => o.Process.Contains(".something1") ? 1 : 0),
                    column3= g.Sum(o => o.Process.Contains(".something2") ? 1 : 0),
                    column4= g.Sum(o => o.Process.Contains("something3") ? 1 : 0),
                    column5= g.Sum(o => o.Process.Contains(".something4") ? 1 : 0),
                    column6 = g.Sum(o => o.Process.Contains(".something5") ? 1 : 0),
                    column7= g.Sum(o => o.Process.Contains(".something6") ? 1 : 0),
                    column8= g.Sum(o => o.Process.Contains(".something7") ? 1 : 0),
                    column9= g.Sum(o => o.Process.Contains(".something8") ? 1 : 0),

                    NumOrgs = g.Select(l => l.OrganizationId).Distinct().Count(),
                    NumUsers = g.Select(l => l.UserId).Distinct().Count(),

                });

            return filter.AsPa......;//not important right now
        }
1
1
6/18/2012 2:09:03 PM

Accepted Answer

If you want to maintain the Anonymous type you can use the InternalsVisibleToAttribute to allow a separate common library to work with the anonymous type.

I have done this previously to make a generic filtering library for datagrids with EF data sources, but it does involve a level of reflection and building the expression out of generic System.Linq.Expression components so this may not be worthwhile unless you have very many instances you want to do this to.

See msdn info:

http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx

and

http://msdn.microsoft.com/en-us/library/system.linq.expressions.expression.aspx

If the select pattern is more predicable you may not need the expression portion, but in that case it may ultimately be simpler to just use a public class instead of the anonymous one.

Edit: "cannot convert anonymous to x" type errors mean you haven't gotten rid of the anonymous entirely/correctly.

In each of the locations you have new { ...whatever... } you are creating an anonymous type. If you create classes for each of those that have the correct properties to match what you are assigning then you just change something that looks like

new {x=1,y=2}

to read

new somenewclass() {x=1,x=2}

assuming you have defined elsewhere

public class somenewclass
{
    public int x {get;set;}
    public int y {get;set;}
}
1
6/19/2012 8:36:44 PM

Popular Answer

You can do like this ,

  var Query = commonFilter.Select(g => new
            {
                Year = g.Key.Year,
                Month = g.Key.Month,
                Day= g.Key.Day,
                TotErr = g.Count(),

                column1 = g.Sum(o => o.Process.Contains("something") ? 1 : 0),
                column2= g.Sum(o => o.Process.Contains(".something1") ? 1 : 0),
                column3= g.Sum(o => o.Process.Contains(".something2") ? 1 : 0),
                column4= g.Sum(o => o.Process.Contains("something3") ? 1 : 0),
                column5= g.Sum(o => o.Process.Contains(".something4") ? 1 : 0),
                column6 = g.Sum(o => o.Process.Contains(".something5") ? 1 : 0),
                column7= g.Sum(o => o.Process.Contains(".something6") ? 1 : 0),
                column8= g.Sum(o => o.Process.Contains(".something7") ? 1 : 0),
                column9= g.Sum(o => o.Process.Contains(".something8") ? 1 : 0),

                NumOrgs = g.Select(l => l.OrganizationId).Distinct().Count(),
                NumUsers = g.Select(l => l.UserId).Distinct().Count(),

            });
    if (request.Equals("some text"))
    {
        var filter = Query.GroupBy(x => new
            {
                x.Timestamp.Year,
                x.Timestamp.Month,
            }) ;
    }
    //Same thing again but slightly different
    else if (request.Equals("some other text"))
    {
        var filter = Query.GroupBy(x => new
            {
                x.Timestamp.Year,
                x.Timestamp.Month,
                x.Timestamp.Day
            });
    }


Related Questions





Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow