如何使用LINQ将DATETIME类型列转为字符串实现模糊搜索
解决方案
报错原因
DateTime类型原生没有Contains方法,且直接调用C#的ToString()方法无法被EF实体框架转换为可执行的SQL语句,因此会触发运行时错误。
推荐方案:数据库端执行(性能最优)
使用EF内置的函数完成DateTime转字符串的操作,整个查询逻辑在数据库端执行,无需加载全量数据到内存,适配大数据量场景。
- 首先引入对应命名空间:
- EF6环境:
using System.Data.Entity; - EFCore环境:
using Microsoft.EntityFrameworkCore;
- EF6环境:
- 修改报错行代码即可,完整修改后代码如下:
public ActionResult Get(string searchString) { DateTime? startDate = new DateTime(2016, 1, 1); DateTime? endDate = new DateTime(2018, 12, 5); AccountingEntities db = new AccountingEntities(); var expensesValues = db.Expenses.AsQueryable(); if (startDate.HasValue && endDate.HasValue) { expensesValues = expensesValues.Where(s => s.Date > startDate && s.Date < endDate); // 仅当搜索值非空时追加模糊匹配条件 if (!string.IsNullOrEmpty(searchString)) { // EF6写法 expensesValues = expensesValues.Where(s => DbFunctions.Like(DbFunctions.ToString(s.Date), $"%{searchString}%")); // EFCore写法(高版本支持直接识别ToString转换) // expensesValues = expensesValues.Where(s => s.Date.ToString().Contains(searchString)); // 如果需要固定格式匹配(比如仅匹配年月日,排除时间部分),可指定格式,例: // expensesValues = expensesValues.Where(s => s.Date.ToString("yyyy-MM-dd").Contains(searchString)); } } // 后续返回结果逻辑自行补充 }
上述写法可满足需求:比如日期为1998年的记录,转字符串后包含字符8,输入8即可命中对应数据。
备选方案:内存端执行(仅适合小数据量场景)
如果数据量极小,可先将符合日期范围的数据加载到内存后,再做模糊匹配,缺点是数据量大时内存占用高、查询效率低。代码示例:
// 先加载符合日期范围的所有数据到内存 var tempList = expensesValues.Where(s => s.Date > startDate && s.Date < endDate).ToList(); // 内存中做模糊匹配 if (!string.IsNullOrEmpty(searchString)) { tempList = tempList.Where(s => s.Date.ToString().Contains(searchString)).ToList(); }
内容的提问来源于stack exchange,提问作者Ehsan
相关产品推荐
相关产品推荐

