Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Convert LINQ Comprehension Query Syntax to Method Syntax using Lambda

Is there a tool, process or a solution that will convert the following LINQ Query Syntax to Method Syntax with Lambdas (dot notation)? I would expect the solution to convert the following Query Syntax to a Method Syntax such as this.

var filteredEmployees = 
    from employee in allEmployees
    where employee.DepartmentID < 4 && employee.EmployeeID < 10
    orderby employee.DepartmentID descending,
            employee.LastName descending
    select employee;

To the following

var filteredEmployees2 = allEmployees.Where(employee => ((employee.DepartmentID < 4) && (employee.EmployeeID < 10)))
        .OrderByDescending(employee => employee.DepartmentID)
        .ThenByDescending(employee => employee.LastName);

I'm would like to use this to learn Method Syntax better.

like image 661
Mike Barlow - BarDev Avatar asked Mar 03 '13 02:03

Mike Barlow - BarDev


3 Answers

LINQPad is a good tool for what you need. I "stole" the following screenshot from their website to better illustrate how it works. If you write a query using linq syntax you can click on the button highlighted in red to see the equivalent lambda syntax:enter image description here

like image 111
Rui Jarimba Avatar answered Oct 24 '22 18:10

Rui Jarimba


If we force the Query Syntax to return a type of IQueryable then we can get to the Method Syntax.

Here I changed the query to return type of IQueryable:

IQueryable<Employee> filteredEmployees = 
    (from employee in allEmployees.AsQueryable()
    where employee.DepartmentID < 4 && employee.EmployeeID < 10
    orderby employee.DepartmentID descending,
            employee.LastName descending
    select employee);

Console.WriteLine(filteredEmployees.ToString());

In the previous code we added "AsQueryable() to the "allEmployees" list type. The return type will now be IQueryable, so "filteredEmployees" will now be of type "IQueryable". Then on the "filteredEmployees" all we need to do is call "ToString()" method.

And the following is written to the console.

System.Collections.Generic.List`1[UserQuery+Employee]
     .Where(employee => ((employee.DepartmentID < 4) AndAlso (employee.EmployeeID < 10)))
     .OrderByDescending(employee => employee.DepartmentID)
     .ThenByDescending(employee => employee.LastName)

It's not perfect, but we can easily edit this to the following

IEnumerable<Employee> filteredEmployees2 = allEmployees
        .Where(employee => ((employee.DepartmentID < 4) && (employee.EmployeeID < 10)))
        .OrderByDescending(employee => employee.DepartmentID)
        .ThenByDescending(employee => employee.LastName);

Console.WriteLine(filteredEmployees);

In the previous code I removed "System.Collections.Generic.List`1[UserQuery+Employee]" and replaced it with "allEmployees". I also replace "AndAlso" with "&&".

This will return the same results as the query in the Query Syntax.

like image 13
Mike Barlow - BarDev Avatar answered Oct 24 '22 19:10

Mike Barlow - BarDev


You can get a more direct expression by declaring a lambda expression which generates some object. The actual expression will be the query you want to see using the query syntax. Then by inspecting the expression tree generated by the compiler, you can see what method calls are made without having to alter the original query.

Expression<Func<object>> fn = () =>
    from employee in allEmployees
    where employee.DepartmentID < 4 && employee.EmployeeID < 10
    orderby employee.DepartmentID descending,
            employee.LastName descending
    select employee;
// inspect fn.Body

Using IQueryable<> as you did there does not generate the same query but slightly modified. The AsQueryable() call you have to ignore. There's also the possibility that the query provider can rewrite the expression so what you get back using ToString() may not have a 1:1 correspondence. The compiler generated expression will be exactly what you would expect.

like image 3
Jeff Mercado Avatar answered Oct 24 '22 19:10

Jeff Mercado