Linq to entities - 使用导航属性重用谓词?

时间:2015-04-20 15:40:02

标签: c# linq entity-framework navigation-properties

我试图找到一种方法来重用谓词来过滤EF 6.1.3中的实体。我使用' Where'来遇到过滤相关属性的问题。

E.g。如果我有这个界面IValidFromTo

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

和一个返回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;
  } 
}

请参阅http://www.albahari.com/nutshell/predicatebuilder.aspx了解背景信息。

直接应用于DbSet时,此方法有效。

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

但是如何使用更复杂的查询来处理导航属性呢?

E.g。如果我的DbSet<Person>集合为Item

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

我希望将它投影到一个包含该人名和仅当前Items的对象中,我最终会得到一些相当混乱的代码:

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

我想知道是否可以改进此代码,例如能够写出像

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

(在ICollection<IValidFromTo>上编写扩展方法不起作用,因为EFf不会识别此方法并抛出错误)

更新

通过Join可以实现这一点(假设每个Person只能有一个有效的项目):

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 };

如果每个Item可能有多个有效Person,那么

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

但是,此版本的查询将排除没有匹配Items的人。

0 个答案:

没有答案