【问题标题】:Dynamic conditions in Linq-to-Entities queryLinq-to-Entities 查询中的动态条件
【发布时间】:2012-10-25 08:50:59
【问题描述】:

我正在尝试将一些直接构建 SQL 查询的旧代码转换为实体框架,并且遇到了许多似乎都有的问题(从围绕该主题的大量问题来看):如何表达动态 where 条件在 linq 中。

我如何用 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 语句?

【问题讨论】:

  • query = query.Where(x=&gt;x.status&lt;0)

标签: c# .net linq entity-framework dynamic


【解决方案1】:

如果你不想使用外部的东西,那么只需使用 fluent API:

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,是的,这将是一个数据库查询,Linq 将推迟执行,直到您调用 foreachToListCount 之类的东西。
  • 谢谢,这正是我想要的。因此只要我只需要动态添加 AND where 条件(或设置排序),我就可以使用它来代替 PredicateBuilder 之类的扩展。
【解决方案2】:

在你的情况下使用PredicateBuilder,如下所示

也请查看我的博文:Dynamic query with 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 );

【讨论】:

  • 感谢您的回答和链接——虽然这更强大,但我一直在寻找没有“扩展”的解决方案。
【解决方案3】:

您可以将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();
}

【讨论】:

    猜你喜欢
    • 2013-05-02
    • 2011-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多