Linq-to-Entities查询中的动态条件

4

我是想将一些旧的直接构建 SQL 查询的代码转换为 Entity Framework,但却遇到了一个问题,很多人都会遇到(从围绕该主题的大量问题来看):如何在 LINQ 中表示动态 where 条件。

我该如何用 LINQ 查询表达以下代码:

    switch (status) {
        case "0":
            sqlwhere = " WHERE status < 0 ";
            break;
        case "-1":
            sqlwhere = " WHERE status = -1 ";
            break;
        case "-100":
            sqlwhere = " WHERE status = -100 ";
            break;
        case "1":
        default:
            sqlwhere = " WHERE status >= 0 ";
            break;
    }

    if (strsearch != "")
        sqlwhere += " AND desc LIKE '%" + strsearch + "%' ";

    string sqlc = "SELECT top 10 * FROM c " + sqlwhere + " order by date desc";

我已经阅读了其他文章中关于PredicateBuilder和动态Linq扩展的内容,但我认为这样一个简单的情况可以不使用外部库来解决。
在使用.net 4.5、EF 5.0和C#的情况下,是否可以以“动态”的方式完成,而不是为每个单独的情况构建完整的linq语句?

1
query = query.Where(x=>x.status<0) - L.B
3个回答

2
在您的情况下,可以使用PredicateBuilder,如下所示。
还请查看我的博客文章:Linq动态查询
var outer = PredicateBuilder.True<Entity>();

switch (status) {
        case "0":
            outer = outer.And (p => p.status<0);
            break;
        case "-1":
            outer = outer.And (p => p.status==-1);
            break;
        case "-100":
            outer = outer.And (p => p.status==-100);
            break;
        case "1":
        default:
            outer = outer.And (p => p.status>=0); 
            break;
    }

if (strsearch != "")
        outer = outer.And (p => p.desc.Contains(strsearch ));

dataContext.Entity.Where (outer );

谢谢你的回答和链接--虽然这个更强大,但我正在寻找一个没有“扩展”的解决方案。 - Tom

2
今日免费次数已满, 请开通会员/明日再来
var query = db.YourTableName
              .Where(x => x.desc.Contains(strsearch));

switch (status) {
   case "0":
        query = query.Where(x => x.status < 0);
        break;
   case "-1":
        query = query.Where(x => x.status == -1);
        break;
   case "-100":
        query = query.Where(x => x.status == -100);
        break;
   case "1":
   default:
        query = query.Where(x => x.status >= 0);
        break;
}

var result = query.OrderByDescending(x => x.date)
                  .Take(10);

顺便提一下,您可以创建一个过滤状态的扩展方法。您的查询将如下所示:

var query = db.YourTableName
              .FilterByStatus(status)
              .Where(x => x.desc.Contains(strsearch))
              .OrderByDescending(x => x.date)
              .Take(10);

扩展方法:

public static IQueryable<YourType> FilterByStatus(this IQueryable<YourType> query, 
                                                  string status)
{

    switch (status) {
       case "0":
            return query.Where(x => x.status < 0);            
       case "-1":
            return query.Where(x => x.status == -1);
       case "-100":
            return query.Where(x => x.status == -100);
       case "1":
       default:
            return query.Where(x => x.status >= 0);
    }
}

使用上述流畅的API语法,所有内容是否都将被翻译为一个SQL查询,从而只产生一次数据库往返?重要的是,所有过滤、排序等操作都将在数据库中完成,以避免检索数千条记录,然后在客户端进行过滤。 - Tom
@Tom,是的,它将是一个数据库查询,Linq会延迟执行直到您调用类似于foreachToListCount的东西。 - Sergey Berezovskiy
谢谢,那正是我在寻找的。只要我只需要动态添加AND where条件(或设置排序),我就可以使用它,而不需要像PredicateBuilder这样的扩展。 - Tom

0

你可以使用 LinkExtensionLinqKit

  using (var context = new workEntities() )
{

    Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>();
    dictionary["Title"] = new List<string> {  
                    "Network Engineer", 
                    "Security Specialist", 
                    "=Web Developer"
                };
    dictionary["Salary"] = new List<string> { ">=2000" };
    dictionary["VacationHours"] = new List<string> { ">21" };
    dictionary["SickLeaveHours"] = new List<string> { "<5" };                
    dictionary["HireDate"] = new List<string> { 
                    ">=01/01/2000",
                    "28/02/2014" 
                };
    dictionary["ModifiedDate"] = new List<string> { DateTime.Now.ToString() };

    var data = context.Employee.CollectionToQuery(dictionary).ToList();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接