【问题标题】:search decimal values in Linq query在 Linq 查询中搜索十进制值
【发布时间】:2015-04-14 08:06:24
【问题描述】:

我有这个搜索词

[HttpPost]
public ActionResult Index(string searchString)
{
    if (!String.IsNullOrEmpty(searchString))
    {
        students = students.Where(s => s.FIRST_NAME.Contains(searchString) 
            || s.LAST_NAME.Contains(searchString)
            || s.PERSONAL_NUMBER.Contains(searchString)
            || s.ACD_UNI_DEGREES.DEGREE.Contains(searchString)
            || s.ACD_UNI_FACULTIES.FACULTY.Contains(searchString)
            || s.ACD_UNI_SPECIALIZATIONS.SPECIALIZATION.Contains(searchString)
            || SqlFunctions.StringConvert(s.SEMESTER).Contains(searchString) 
            || s.COR_PAYER_STATUS.NAME.Contains(searchString)
            || SqlFunctions.StringConvert(s.CREDIT_COUNT).Contains(searchString));
    }

    return View(students.ToList());
}

但在调试时会抛出异常:

System.NotSupportedException:指定的方法'System.String StringConvert(System.Nullable`1[System.Decimal])' 关于类型 'System.Data.Objects.SqlClient.SqlFunctions' 无法翻译成 一个 LINQ to Entities 存储表达式。

问题出在这里:

SqlFunctions.StringConvert(s.SEMESTER).Contains(searchString)

SEMESTER 是十进制,searchString 是字符串。 我该如何改进呢?

【问题讨论】:

  • 制作一个存储过程,将小数列转换为字符串并在服务器上进行“喜欢”比较。通过 SqlClient 调用存储过程
  • 因为它可以为空,你可以先检查s.SEMESTER != null && s.SEMESTER.HasValue然后s.SEMESTER.Value.ToString().Contains(searchString)
  • 你有什么样的数据库?
  • @默认是甲骨文。但我首先使用的是 EF db
  • 好吧,您可以随时提前致电.ToList(),然后进行进一步检查。但是根据documentation,你不能直接调用这个函数。此函数只能出现在 LINQ to Entities 查询中。因此您必须以其他方式编写逻辑(我猜是通过 s.Semester.ToString()?)。所以.Where(s => s./* methods that can be translated*/).ToList().Where(s => s./* methods that cannot be translated*/);

标签: c# linq entity-framework


【解决方案1】:

您应该确保您使用的是System.Data.Entity.SqlServer.SqlFunctions。我重写了您的查询,一切正常。

【讨论】:

    【解决方案2】:

    虽然这是一个旧问题发布答案,但其他人会正确地做到这一点
    首先要纠正的是我们需要将第一个整数转换为十进制然后搜索,假设可搜索列的数据类型也是十进制

    所以首先将您的搜索字符串转换为十进制

                   decimal dec;
                   bool IsDecimal = decimal.TryParse(searchString, out dec);
    
                   // Truncating search to 2 digits this should be equal to your db            
                   // column precision so that rounding case are handled properly 
                   decimal TruncateDigits = -1;
                   if (IsDecimal)
                       TruncateDigits = Convert.ToDecimal(Math.Truncate(dec * 100) / 100); 
    

    现在您的搜索字段与您的 db 列精度 相同,可以进行搜索了

        students = students.Where(s => s.FIRST_NAME.Contains(searchString) 
                || s.LAST_NAME.Contains(searchString)
                || s.PERSONAL_NUMBER.Contains(searchString)
                || s.ACD_UNI_DEGREES.DEGREE.Contains(searchString)
                || s.ACD_UNI_FACULTIES.FACULTY.Contains(searchString)
                || s.ACD_UNI_SPECIALIZATIONS.SPECIALIZATION.Contains(searchString)
                || (IsDecimal && (decimal.Round(s.SEMESTER, 2) == TruncateDigits)) 
    

    注意事项

          (IsDecimal && (decimal.Round(s.SEMESTER, 2) == TruncateDigits)) 
    

    这里我们将再次舍入到 db 列精度来处理舍入。

    另外 SqlFunctions.StringConvert 将在内部进行舍入所以如果你的数字是 db 是 68.88 并且你正在搜索 68 它不会搜索因为 StringConvert 会给你 69(舍入)所以如果你想搜索对于 68 则您需要使用 Floor 功能
    类似

         SqlFunctions.StringConvert(decimal.Floor(s.SEMESTER)).Contains(searchString) 
    

    希望这会有所帮助!!!

    【讨论】:

      【解决方案3】:

      我现在面临同样的问题,与您的目标完全相同。找了好久,终于找到了这个:

      [HttpPost]
      public ActionResult Index(string searchString){
          searchString = searchString.Replace(",", ".");
      
          if (!String.IsNullOrEmpty(searchString)){
              students = students.Where(s => s.FIRST_NAME.Contains(searchString) 
              || s.LAST_NAME.Contains(searchString)
              || s.PERSONAL_NUMBER.Contains(searchString)
              || s.ACD_UNI_DEGREES.DEGREE.Contains(searchString)
              || s.ACD_UNI_FACULTIES.FACULTY.Contains(searchString)
              || s.ACD_UNI_SPECIALIZATIONS.SPECIALIZATION.Contains(searchString)
              || (s.SEMESTER.ToString()).Contains(searchString) 
              || s.COR_PAYER_STATUS.NAME.Contains(searchString)
              || SqlFunctions.StringConvert(s.CREDIT_COUNT).Contains(searchString));
          }
          return View(students.ToList());
      }
      

      您通常使用ToString()decimal 转换为string。然而,括号是这里的法宝: (s.SEMESTER.ToString()) 这会有所不同。

      此语法将允许您使用符号 . 进行搜索(例如:1203.4 而不是 1203,4)。这不是真正的用户友好。

      要解决此问题,请在 searchString 上使用 .Replace(',', '.')。这将把技巧应用到背景上,没有人会注意到。

      我希望它可以帮助任何遇到同样问题的人。

      【讨论】:

        猜你喜欢
        • 2017-11-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-25
        • 1970-01-01
        相关资源
        最近更新 更多