使用linq过滤列表

时间:2014-04-29 09:52:38

标签: c# sql linq entity-framework

我正在写信寻求帮助,如何过滤数据然后合并两个结果,如下所示:

更新代码*

public class TestController : ApiController
{
    private cdw db = new cdw();

    public HttpResponseMessage get([FromUri] Query query)
    {
        var data = db.data_qy.AsQueryable();

        if (query.startDate != null)
        {
            data = data.Where(c => c.UploadDate >= query.startDate);
        }

        if (!string.IsNullOrEmpty(query.tag))
        {
            var ids = query.tag.Split(',');

            data = data.Where(c => c.TAG.Any(t => ids.Contains(t)));
        }

        if (!string.IsNullOrEmpty(query.name))
        {
            var ids = query.name.Split(',');

            data = data.Where(c => c.NAME.Any(t => ids.Contains(t)));
        }

        if (!data.Any())
        {
            var message = string.Format("No data found");
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, message);

        }

        return Request.CreateResponse(HttpStatusCode.OK, data);
    }
}

实体类:

  public partial class data_qy
   {
    public int ID { get; set; }


    public string Name { get; set; }

    public string TAG { get; set; }

    public string TAG_IS { get; set; }

    [Newtonsoft.Json.JsonProperty(PropertyName = "Date")]
    public Nullable<System.DateTime> UploadDate { get; set; }

}

示例数据集:

 Name               Tag          Tag_IS
 AMCAR 2013-5   03065EAC9   
 ARES 2006-6RA  04009JAA9   
 ARES 2012-1A   04013TAB9   
 ATOM 2003-I A           0182690668
 BACM 2006-2 AM 05950EAG3   
 BCAP 2007-AA3  05530VAN9   
 BCAP 2007-AA3  05530VAN9   
 BCJAF 9 C                   0312888037
 BLNDLN 0                    0213093627
 BLNDLN 0                    0213093627

底层SQL查询应该类似于:

select * 
from [dbo].[data_qy] 
where TAG like '%78473TAC4%' 
    or TAG LIKE '%05946XYZ0%' 
    OR NAME LIKE '%TAP%' 
    OR NAME LIKE '%STORM%'

使用上面的以下列表方法,当我运行诸如(api/test/tag=78473,12669,05946,...(30个值))的查询时,我得到一个 - 异常消息:

  

SQL语句的某些部分嵌套太深。重写查询或将其分解为较小的查询

我错过了什么。非常感激任何的帮助。 感谢

1 个答案:

答案 0 :(得分:1)

我不是在现场对此进行测试,但我怀疑以下任何一种都应该有效:

public class TestController : ApiController
{
    private cdw db = new cdw();

    public HttpResponseMessage get([FromUri] Query query)
    {
        IQueryable<data_qy> data = null;

        if (!string.IsNullOrEmpty(query.tag))
        {
            var ids = query.tag.Split(',');

            var dataMatchingTags = db.data_qy.Where(c => ids.Any(id =>  c.TAGS.Contains(id)));

            if (data == null)
                 data = dataMatchingTags;
            else
                 data  = data.Union(dataMatchingTags);
        }

        if (!string.IsNullOrEmpty(query.name))
        {
            var ids = query.name.Split(',');

            var dataMatchingName = db.data_qy.Where(c => ids.Any(id =>  c.NAME.Contains(id)));

            if (data == null)
                 data = dataMatchingName;
            else
                 data  = data.Union(dataMatchingName);
        }

        if (data == null) // If no tags or name is being queried, apply filters to the whole set of products
            data = db.data_qy;

        if (query.startDate != null)
        {
            data  = data.Where(c => c.UploadDate >= query.startDate);
        }

        var materializedData = data.ToList();

        if (!materializedData.Any())
        {
            var message = string.Format("No data found");
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, message);

        }

        return Request.CreateResponse(HttpStatusCode.OK, materializedData);
    }
}

我还怀疑您不需要在查询中检查Null,因为EF在将表达式树转换为SQL时会理解,但如果需要,您可以添加它。

这样就无需使用foreachAggregateCount调用。并导致一个更简单的查询,应该在SQL中使用IN运算符。

目前你正在多次执行相同的查询(最后调用.Any将执行查询,然后传递数据变量将再次执行它。这可能非常昂贵。相反,实现了结果并采取行动,如上所述。