如何动态修改LinQ查询?

时间:2018-10-11 06:40:44

标签: c# entity-framework linq lambda asp.net-web-api2

我基本上有一个WebAPI服务,该服务将值返回给客户端。

我有一个控制器来处理documents请求,可以通过简单的enum对它们进行参数化。

这个简单的枚举提供了这样的选择:

public enum DataRange
{
    Last7Days,
    Last30Days,
    Last90Days,
    ThisYear,
    Last10,
    Last50,
    Last100,
    Last500,
    All
}

我想在DBContext实际处理查询之前“动态”修改LinQ查询,从而避免了我创建一个痛苦的switch来复制代码,而且它不是那么容易阅读,甚至优雅。

我实际上已经解决了创建两种不同方法的问题,这取决于所涉及的Take(x)还是DateTime .Where()过滤器,这让我感到有些紧张。

在此方法中,我基于与查询类似的lambda返回.Take(x)

private IQueryable<Documents> GetQueryByRegistries(DataRange dataRange)
{    
    switch (dataRange)
    {
        case DataRange.Last10:
            return Context.Documents
                              .Where(x => x.Auditoria)
                              .Include(x => x.Variables)
                              .Include(x => x.Events)
                              .OrderBy(x => x.Creation)
                              .Take(10);

        case DataRange.Last50:
            return Context.Documents
                              .Where(x => x.Auditoria)
                              .Include(x => x.Variables)
                              .Include(x => x.Events)
                              .OrderBy(x => x.Creation)
                              .Take(50);
                ...
        case DataRange.All:
            return Context.Documents
                              .Where(x.Auditoria)
                              .Include(x => x.Variables)
                              .Include(x => x.Events)
                              .OrderBy(x => x.Creation);

        default:
            return Context.Documents
                              .Where(x => x.Auditoria)
                            .Include(x => x.Variables)
                            .Include(x => x.Events)
                            .OrderBy(x => x.Creation);
    }
}


private IOrderedQueryable<Documents> GetQueryByDays(DataRange dataRange)
{
    var limitDateTime = DataRange.GetClause(dataRange);
    var documents = Context.Documents
                              .Where(x => x.Auditoria
                                  && x.Creation >= limitDateTime)
                                     .Include(x => x.Variables)
                                     .Include(x => x.Events)
                                     .OrderBy(x => x.Creation);
    return documents;
}

在这里,我为where子句处理DateTime的创建:

public static DateTime GetClause(DataRange dateTimeRange)
{
    switch (dateTimeRange)
    {
        case DataRange.Last7Days:
            return Last7Days();
        case DataRange.Last30Days:
            return Last30Days();
        case DataRange.Last90Days:
            return Last90Days();
        case DataRange.EsteAno:
            return ThisYear();
        default:
            return BigBang();
    }
}

由于我一直在尝试avoid using switch个场景,因此我想即时修改query,避免创建这两个又大又丑的switch,并阻止我这样做对查询本身进行参数设置,强制重复代码。

我尝试了LinqKit,但老实说,我真的不知道如何将自己的需求应用到其中。

预先感谢,希望示例对您有所帮助。

1 个答案:

答案 0 :(得分:1)

我了解的是您想根据您的枚举更改查询。我想这就是你想要的。

private IQueryable<Documents> GetQueryByRegistries(DataRange dataRange)
{    
  // this is your base query. which will be common for all conditions.
  var query = Context.Documents
                          .Where(x => x.Auditoria)
                          .Include(x => x.Variables)
                          .Include(x => x.Events);

 switch (dataRange)
 {
    case DataRange.Last10:
        return query.Where(x => x.SomeId == 10).OrderBy(x => x.Creation)
                          .Take(10); // if you want to add Where again you can do that

    case DataRange.Last50:
        return query.OrderBy(x => x.Creation)
                          .Take(50);
            ...
    case DataRange.All:
        return query.OrderBy(x => x.Creation);

    default:
        return query.OrderBy(x => x.Creation);
  }
}