【问题标题】:Linq query to db with dynamic where parameters使用动态 where 参数对 db 进行 Linq 查询
【发布时间】:2014-07-29 19:06:15
【问题描述】:

我有一张包含城市数据的表格: 在搜索输入字段中,用户键入任意数量的字符,然后按下“搜索”按钮。 还有另一个字段,用户可以通过下拉列表输入状态。

按下搜索按钮会触发对服务器控制器的 ajax 调用,该控制器接收名称的起始字符和状态的两个字符。

控制器应返回名称以提供的字符开头的城市列表。 如果通过了州,则列表应仅包含名称以提供的字符开头且位于州内的城市。

如果未通过州,则无论州如何,都会返回所有匹配的城市。

我找不到编写单个 Linq 语句的方法,因为我不知道如何编写状态查询部分: 目前我这样做:

public ActionResult selectCity(string searchString, string stateCode)
{
    List<CityViewModel> mylist = new List<CityViewModel>();
    IQueryable<City> mycities = null;

    if (stateCode == "")
    {
        mylist = (from c in db.Cities
                    where c.name.StartsWith(searchString)
                    select c);
    }
    else
    {
        mylist = (from c in db.Cities
                    where ((c.name.StartsWith(searchString)) &&
                          (c.stateCode == stateCode))
                    select c);
    }

    <snip>
    .....
    .....
    </snip>

   return PartialView("_selComune",elenco);
}

我不敢相信没有办法通过单个查询来做到这一点。

【问题讨论】:

    标签: c# asp.net-mvc linq wildcard


    【解决方案1】:

    是的,有。

    您想:如果stateCode 为空或匹配City.stateCode,则将其包含在结果中,而且City.Name 必须始终以searchString 开头。在代码中:

    var mylist = 
        from c in db.Cities
        where 
            c.name.StartsWith(searchString) 
            && (stateCode == "" || c.stateCode == stateCode)
        select c;
    

    大致相当于这个 SQL(假设提供了正确语法的参数):

    SELECT * FROM Cities
    WHERE name LIKE @searchString AND (@stateCode = '' OR stateCode = @stateCode)
    

    如果始终满足第一个条件,SQL Server 将优化第二个比较(只需检查查询执行计划)。


    我认为这是一个拼写错误的代码示例,但myList 不是List&lt;City&gt;,除非您还将ToList() 添加到您的LINQ 查询中。

    【讨论】:

    • ... 像往常一样,答案简单明了;当我们有“AND”和“OR”时,为什么还要使用通配符......谢谢你记住我这条黄金法则
    【解决方案2】:

    Adriano Repetti 的回答允许您编写单个查询来处理“可空”参数,但有时它存在性能缺陷,在 SQL 中翻译为这种查询可能会阻止索引工作。

    请注意,以下内容也将起作用,并在 sql 端构建所需的确切查询,在 LINQ 端只需要更多代码:

        mylist = (from c in db.Cities
                  where c.name.StartsWith(searchString)
                  select c);
    
        if (stateCode != "")
        {
            mylist = mylist.Where(c.stateCode == stateCode);
        }
    

    这种结构不会替换以前的“where”内容,它会添加任何新的术语,将它们与“and”运算符结合起来。

    IQeryable 允许您在许多不同的行中构建它,而不是像您在代码示例中所做的那样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-03
      • 2010-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-25
      • 2021-08-20
      相关资源
      最近更新 更多