C#LINQ使变量where语句

时间:2017-04-14 07:48:25

标签: c# linq

我有一个适用于我的搜索结果的过滤器。

我现在拥有以下内容:

Filter 1 = Any
Filter 2 = Atlas
Filter 3 = phoenix

现在当过滤器在任何上时,我运行以下查询:

foreach (DetectorStatu status in loadOperation.Entities.OrderBy(d => d.Status).Take(25).Reverse())

当过滤器处于 Atlas

foreach (DetectorStatu status in loadOperation.Entities.OrderBy(d => d.Status).Where(d => ((d as DetectorStatu).Detector as Detector).EnabledDetectorTypes.Count(t => t.DetectorTypeID == 1) > 0).Take(25).Reverse())

当过滤器在 Phoenix 上时:

foreach (DetectorStatu status in loadOperation.Entities.OrderBy(d => d.Status).Where(d => ((d as DetectorStatu).Detector as Detector).EnabledDetectorTypes.Count(t => t.DetectorTypeID == 2 || t.DetectorTypeID == 3) > 0).Take(25).Reverse())

他们正在调用的实际查询:

[Query]
[OutputCache(OutputCacheLocation.Server, 60)]
public IQueryable<DetectorStatu> GetDetectorDatabacklog(int userID)
{
    User user = ObjectContext.Users
    .Include("TeamMemberships")
    .First(u => u.UserID == userID);

    var teamIDs = user.TeamMemberships.Select(t => t.TeamID).ToList();
    var siteIDs = ObjectContext.SiteMemberships.Where(t => teamIDs.Contains(t.TeamID)).Select(t => t.SiteID).ToList();

    var DetectorStatus = ObjectContext.DetectorStatus
        .Include("Detector")
        .Include("Detector.Track")
        .Include("Detector.Site")
        .Include("Detector.EnabledDetectorTypes")
        .Include("Detector.EnabledDetectorTypes.DetectorType")
        .Where(d => siteIDs.Contains(d.Detector.SiteID))
        .OrderBy(d => d.Status);

    return DetectorStatus;
}
  

现在我的问题:

有没有办法让这种动态/更短?

现在我通过if语句检查过滤器,然后运行所有代码。 但是,我想再添加8个过滤器。并且如果声明会使代码变得非常大且非常不清楚,那么再增加8个 我基本上添加了50行代码,而我只需要更改1行查询。

3 个答案:

答案 0 :(得分:4)

您可以通过多个步骤构建查询:

IQueryable<DetectorStatu> query = loadOperation.Entities.OrderBy(d => d.Status);

然后根据您的设置添加过滤器:

if (<filter is Atlas>)
{
  query = query.Where(d => ((d as DetectorStatu).Detector as Detector).EnabledDetectorTypes.Count(t => t.DetectorTypeID == 1) > 0);
}
else if (<filter is Phoenix>)
{
  query = query.Where(d => ((d as DetectorStatu).Detector as Detector).EnabledDetectorTypes.Count(t => t.DetectorTypeID == 2 || t.DetectorTypeID == 3) > 0);
}

等等。当然,您必须用<filter is ...>替换正确的代码。

最后你只有一个 foreach语句:

query = query.Take(25).Reverse();
foreach (DetectorStatu status in query) { ... }

在您输入foreach时,只会向数据库发送一个查询。这将考虑从“OrderBy”到“Reverse”的所有步骤。

答案 1 :(得分:2)

可以定义System.Linq.Expression:

Expression<Func<DetectorStatu, bool>> filter = null;

if(any){
   filter = x => true;
}

if(Atlas){
   filter = d => ((d as DetectorStatu).Detector as Detector).EnabledDetectorTypes.Count(t => t.DetectorTypeID == 1) > 0
}

if(Phoenix){
   filter = d => ((d as DetectorStatu).Detector as Detector).EnabledDetectorTypes.Count(t => t.DetectorTypeID == 2 || t.DetectorTypeID == 3) > 0;
}

最后:

foreach (DetectorStatu status in loadOperation.Entities.OrderBy(d => d.Status)
   .Where(filter)
   .Take(25).Reverse())

答案 2 :(得分:0)

Where子句只需要一个谓词(一个返回bool的Func),你可以将它作为参数传递给你的函数。所以基本上你可以为每个&#34; Filter&#34;传递不同的谓词。选项并将其应用于您的IQueryable Where子句