user473104
user473104

Reputation: 311

Building up linq querys as functions

var query = (from material in dataContext.Materials
             join materialCategories in dataContext.MaterialCategories on material.Id equals
             materialCategories.Material.Id
             select new
                    {
                        material.Id,
                        material.Name,
                        material.Taken,
                        materialCategories.CategoryName
                    });
//Filter by date
query = query.Where(x => x.Taken >= minDate && x.Taken <= maxDate);

I want to extract the "query.Where(x => x.Taken >= minDate && x.Taken <= maxDate);" to a function that returns a query but the problem is that the function does not understand what x.Taken is.

How do i achieve this?

Upvotes: 0

Views: 135

Answers (6)

Maciej
Maciej

Reputation: 7961

You need to use a named type instead of an unnamed one. Make a new class:

public class Category
{
    int Id;
    string Name;
    DateTime Taken;
    string CategoryName;
}

You can make fields as properties if you want.

Then instead of:

select new {...}

use your class:

select new Category {...}

And after that you can have this:

private IQueryable<Category> FilterFunction(IQueryable<Category> query)
{
    query = query.Where(x => x.Taken >= minDate && x.Taken <= maxDate);
    return query;
}

Or use IEnumerable<> depending on what you are doing here exactly.

Upvotes: 3

Robert Levy
Robert Levy

Reputation: 29073

You really don't want to do this. Leaving queries in LINQ syntax lets the framework optimize the data queries. If you pull this out into a function, all the data would have to be returned from the database and then filtered client-side. Yuck! For more, see "Why Convert a LINQ to SQL Query Expression into an Expression Tree?" in http://blogs.msdn.com/b/charlie/archive/2008/01/31/expression-tree-basics.aspx

Upvotes: -1

dashton
dashton

Reputation: 2704

You will need to promote your object to become a real type, rather than anopnymous type and then you can do:

 private static Func<YourObject, bool> Predicate(DateTime minDate, DateTime maxDate)
        {
            return x => x.Taken >= minDate && x.Taken <= maxDate;
        }

Upvotes: 1

Wegged
Wegged

Reputation: 2413

You cant do this with anonymous objects w/o some hackery with reflection. I would make a class that has these properties and return IENumerable from the function.

Upvotes: 0

Servy
Servy

Reputation: 203814

Generics will do all of this for you.

public IQueryable<T> betweenDates<T>(IQueryable<T> query, DateTime maxdate, DateTime mindate) where T : YourClass
{
  return query.Where(x => x.Taken >= minDate && x.Taken <= maxDate);
}

Upvotes: 0

Fedor Hajdu
Fedor Hajdu

Reputation: 4697

You can't pass anonymous object to a method. You'd have to create a type and return new instance of that type from your first query.

Upvotes: 0

Related Questions