Linq for objects - reusing predicates with navigation properties?

I'm trying to find a way to reuse predicates to filter objects in EF 6.1.3. I am facing the problem of filtering related properties using "Where".

eg. if i have this interfaceIValidFromTo

public interface IValidFromTo
{
   DateTime StartDate { get; set;}
   DateTime EndDate { get; set; }
}

      

and a function that returns a predicate for Where

:

public class Extensions 
{
  public static Expression<Func<T, bool>> Current<T>() 
  where T : IValidFromTo
  {
    var currentDate = DateTime.Now; 
    return x => x.StartDate <= currentDate && x.EndDate >= currentDate;
  } 
}

      

See http://www.albahari.com/nutshell/predicatebuilder.aspx for background.

When applied directly to a DbSet, this method works.

var query = ctx.Items.Where(Extensions.Current<Item>()); // compiles

      

But how do you make it work for a more complex query about navigation properties?

eg. if i have DbSet<Person>

with a set Item

:

public class Person
{
  ...
  public virtual ICollection<Item> Items { get; set; }
}

      

and I want to project it into an object containing the person's name, and only the current one Items

, I end up with some pretty cluttered code:

var relationQuery = ctx.People.Select(x => new 
    { Name = x.Name,
      CurrentItems = x.Items.AsQueryable().Where(Extensions.Current<Item>())
    });

      

I wonder if this code can be improved, for example? to write something like

CurrentItems = x.Items.Current() // quasi an extension method on `ICollection<Item>`?

      

(writing the extension method ICollection<IValidFromTo>

doesn't work because EFf doesn't recognize this method and doesn't throw an error)

UPDATE

This seems to be achieved with Join

(suppose each Person

can only have one valid element):

var isCurrent= x => <<some condition on x>>;
...  
var validItems = ctx.Items.Where(isCurrent);
var peopleWithCurrentItems = from person in ctx.Persons
                                join item in validItems on person.Id equals item.Owner.Id
                                select new { Person = person, Item = item };

      

If there can be several valid Item

for Person

, then

var grouped = peopleWithValid.GroupBy(x => x.Person);

      

However, this version of the query excludes people without a match Items

.

+3


source to share





All Articles