How to pass a LINQ result to a method?

Right now you are creating a collection that's based on an anonymous type (actually two anonymous types), which cannot practically be passed to another method (other than by using reflection or dynamic). The cleanest way is to create a concrete type that represents the collection - something like

public class ActivityGroup
{
    public DateTime Fecha {get; set;}
    public IEnumerable<Activity> Activities {get; set;}
}

public class Activity
{
    public IEnumerable<Activity> Actividades {get; set;}
    public string NombreEmpleado {get; set;}
}

then change your query to:

var queryActividades = listaActividad
                .GroupBy(a => a.Fecha, (fecha, fechaActividades) => new ActivityGroup
                {
                    Fecha = fecha,
                    FechaActividades = fechaActividades
                        .GroupBy(a => a.Empleado, (nombreEmpleado, actividadesEmpleado) => new Activity
                        {
                            Actividades = actividadesEmpleado,
                            NombreEmpleado = nombreEmpleado
                        })
                        .OrderBy(a => a.NombreEmpleado)
                })
                .OrderBy(a => a.Fecha);

and pass it as an IEnumerable<ActivityGroup>


You can use the approach presented by D Stanley. But it would be kind a boring to have to create such classes for any similar query that you write in the future. Instead, you can introduce as generic class for that, like this

public class Grouping<TKey, TElement>
{
    public TKey Key { get; set; }
    public IEnumerable<TElement> Elements { get; set; }
}

and use it instead of the anonymous types like this

var queryActividades = listaActividad
    .GroupBy(a => a.Fecha, (fecha, fechaActividades) => new Grouping<DateTime, Grouping<string, ActividadEmpleado>>
    {
        Key = fecha,
        Elements = fechaActividades
            .GroupBy(a => a.Empleado, (nombreEmpleado, actividadesEmpleado) => new Grouping<string, ActividadEmpleado>
            {
                Key = nombreEmpleado,
                Elements = actividadesEmpleado
            })
            .OrderBy(a => a.Key)
    })
    .OrderBy(a => a.Key);

which can be be passed as IEnumerable<Grouping<DateTime, Grouping<string, ActividadEmpleado>>>.

As you can see, there is a trade off between reusability and readability. Basically this is a Tuple with a little more meaningful names. Note that although we cannot improve the verbosity in the result, we can use a similar technique to Tuple.Create to remove the verbosity inside the query, by adding a class like this

public static class Grouping
{
    public static Grouping<TKey, TElement> Create<TKey, TElement>(TKey key, IEnumerable<TElement> elements)
    {
        return new Grouping<TKey, TElement> { Key = key, Elements = elements };
    }
}

and use it like this

var queryActividades = listaActividad
    .GroupBy(a => a.Fecha, (fecha, fechaActividades) => Grouping.Create(
        fecha, fechaActividades
            .GroupBy(a => a.Empleado, (nombreEmpleado, actividadesEmpleado) => Grouping.Create(
                nombreEmpleado, actividadesEmpleado))
            .OrderBy(a => a.Key)))
    .OrderBy(a => a.Key);

You can't pass anonymous types between methods; if you need to pass the data to another method, you need to create an explicit named type that contains the Actividades and NombreEmpleado properties, and another one with Fecha and FechaActividades.


Comments

  1. William

    • 2015/5/22

    The LINQ query variable reorders the result in the way i need, which is to store by date and then by ActividadEmpleado and a string. However, 

  2. Cruz

    • 2015/12/2

    The LINQ query variable reorders the result in the way i need, which is to store by date and then by ActividadEmpleado and a string. However, var types cannot be passed to methods, so searching this site i am finding out that i either need to create a class to store the results or to modify the LINQ variable to return a List, but i am having

  3. Francis

    • 2019/11/20

    I have 2 linq queries, 1 get data by name the other by id, both return but I can't seem to pass the results to a method and still have in.

  4. Shane

    • 2015/9/25

    Write a generic method: static void ShowResults<T> (IEnumerable<T> results, int limit) { int i = 0; foreach (T r in results) { if (i < limit) Console.WriteLine ( (i + 1) + ": " + r.ToString ()); i++; } Console.WriteLine ("\r Records: " + i); } Marked as answer by Harry Zhu Monday, April 12, 2010 5:56 AM.

  5. Mario

    • 2016/1/27

    Hi, I have the following linq code within my app var results = (from t in query where t.ProjectID == new Guid(this.Session["ProjectID"].

  6. Joey

    • 2015/7/8

    Joining Collections with LINQ Your first step is to call the GroupJoin method from the collection you want all the objects from (that's Customers in my example). You must pass the GroupJoin method four parameters: The collection you want to join to (the collection that might be missing items; SalesOrders, in this case)

  7. Gordon

    • 2021/2/16

    However, this defeats the strong typing of the anonymous type. If you must store your query results or pass them outside the method boundary, 

  8. Muhammad

    • 2021/1/19

    Now you can call the method in your expression, passing in a lambda representing the desired field (or field expression) to test: var tmp = context.Terms.Include(x => x.StudentCourses).AsQueryable() .Where(x => x.StudentID == studentId && x.DepartmentID == departmentId) .OrderBy(x => x.AcademicYear) .ThenBy(Util.TermsOrder<Term>(p => p.TermRegistered));

  9. Ferri

    • 2020/4/13

    If the type doesn't have its own method overload, you have to pass a delegate parameter. In C#, you can use a lambda expression for this purpose 

  10. Williams

    • 2021/2/3

    The following code example shows how to use the Median method for an array of type double. C#. double[] numbers = { 1.9, 2, 8, 4, 5.7, 6, 7.2, 0 }; var query = numbers.Median (); Console.WriteLine ("double: Median = " + query); /* This code produces the following output: Double: Median = 4.85 */.

  11. Colten

    • 2016/1/3

    You must pass the GroupJoin method four parameters: The collection you want to join to (the collection that might be missing items; SalesOrders, 

  12. Apollo

    • 2017/7/19

    The following figure illustrates the structure of LINQ method syntax. LINQ Method Syntax Structure. As you can see in the above figure, method syntax comprises of extension methods and Lambda expression. The extension method Where() is defined in the Enumerable class. If you check the signature of the Where extension method, you will find the Where method accepts a predicate delegate as Func<Student, bool>. This means you can pass any delegate function that accepts a Student object as an

  13. Deacon

    • 2017/7/30

    The Join method in LINQ takes three Expression parameters to do its job: a pair of key selectors (one for each side of the join) and a select 

  14. Zyaire

    • 2019/7/24

    Accept Solution Reject Solution. Since you asked for both syntax forms: C#. Copy Code. public int GetIDFromName ( string fruitName ) { // LINQ functions: Fruit f = ListOfFruits.FirstOrDefault (x => x.Name == fruitName); // LINQ SQL-ish: Fruit f = ( from x in ListOfFruits where x.Name == fruitName select x).FirstOrDefault (); // (common to both): return f != null ? f.ID : -1; // some value to indicate no such fruit }

  15. Zachary

    • 2018/11/30

    The LINQ query variable reorders the result in the way i need, which is to store by date and then by ActividadEmpleado and a string.

  16. William

    • 2015/6/22

    Passing a method to a LINQ query call the Invoke method on them and pass our lambda expressions' arguments to. ToList(); return JsonNet(result); } }.

  17. Zakai

    • 2019/12/31

    My view currently sends the GenreId to the Controller. The method has the following Linq:- <pre>var query =( from DM in c.DiscMain where DM.

Comments are closed.

Recent Posts