不区分大小写的lambda表达式

本文关键字:lambda 表达式 大小写 不区 | 更新日期: 2023-09-27 18:09:36

我正在使用Visual Studio 2015, Entity Framework 6,并试图构建一个LINQ表达式来获取基于动态WHERE子句的结果。用户可以选择搜索"employeeId"、"securityId"(字符串)或"lastName"。对于姓氏,它应该执行不区分大小写的搜索,因此用户可以输入大写或小写的searchValue

这是我得到的:

public async Task<ObservableCollection<EmployeeViewModel>> 
    SearchEmployeesAsync(string selectedColumn, string searchValue)
{   
    var paramEmployee = Expression.Parameter(typeof(Employee), "e");
    Func<EmployeeBase, bool> comparison = null;
    if (selectedColumn.Equals("employeeId"))
    {
        var employeeId = -1;
        int.TryParse(searchValue, out employeeId);
        comparison = Expression.Lambda<Func<Employee, bool>>(
            Expression.Equal(
                Expression.Property(paramEmployee, selectedColumn),
                Expression.Constant(employeeId)),
            paramEmployee).Compile();
    }
    else
    {
        comparison = Expression.Lambda<Func<Employee, bool>>(
            Expression.Equal(
                Expression.Property(paramEmployee, selectedColumn),
                Expression.Constant(searchValue)),
            paramEmployee).Compile();
    }
    using (var context = new MyEntities())
    {
        var query = (from e in context.Employees
            .Where(comparison)
            select new EmployeeViewModel
            {
                // Populate view model from entity object here
            });
        return await Task.Run(() => new ObservableCollection<EmployeeViewModel>(query));
    }
}

如何更改上述代码,使comparisonsecurityIdlastName(两者都是数据库上的字符串)的搜索不区分大小写?securityIdlastName由上面的else块覆盖。如果有更好的方法,我也愿意重构代码。我不想做的一件事是使用第三方库来编写动态WHERE子句。

谢谢。

不区分大小写的lambda表达式

如果希望在数据库中而不是在内存中应用过滤,则必须在Where子句中使用Expression<Func<Employee, bool>>,而不是在代码中使用Func<Employee, bool>。使用ToLower方法可以模拟不区分大小写的比较。

另外,正如其他人提到的那样,通过使用System.Data.Linq.QueryableExtensions中的ToListAsync方法来消除Task.Run调用会更好。

话虽如此,实现可能是这样的:

using System.Data.Entity;
public async Task<ObservableCollection<EmployeeViewModel>> 
    SearchEmployeesAsync(string selectedColumn, string searchValue)
{
    var parameter = Expression.Parameter(typeof(T), "e");
    Expression left = Expression.PropertyOrField(parameter, selectedColumn);
    object value = searchValue;
    if (selectedColumn == "employeeId")
    {
        var employeeId = -1;
        int.TryParse(searchValue, out employeeId);
        value = employeeId;
    }
    else
    {
        // case insensitive
        left = Expression.Call(left, "ToLower", Type.EmptyTypes);
        value = searchValue.ToLower();
    }
    var comparison = Expression.Lambda<Func<T, bool>>(
        Expression.Equal(left, Expression.Constant(value)),
        parameter);
    using (var context = new MyEntities())
    {
        var query = context.Employees
            .Where(comparison)
            .Select(e => new EmployeeViewModel
            {
                // Populate view model from entity object here
            });
        var result = await query.ToListAsync();
        return new ObservableCollection<EmployeeViewModel>(result);
    }
}

我建议用简单的方法。我质疑这个任务。跑,但因为这不是问题的一部分,所以我不去管它。

public async Task<ObservableCollection<EmployeeViewModel>> 
    SearchEmployeesAsync(string selectedColumn, string searchValue)
{   
  using (var context = new MyEntities())
  {
    var query = context.Employees.AsQueryable();
    switch(selectedColumn)
    {
      case "employeeId":
        var employeeId = -1;
        int.TryParse(searchValue, out employeeId);
        query = query.Where(e=>e.employeeId == employeeId);
        break;
      case "lastName":
        query = query.Where(e=>e.lastName == searchValue);
        break;
      case "securityId":
        query = query.Where(e=>e.securityId == searchValue);
        break;
      }
      query = query.Select(e=> new EmployeeViewModel
            {
                // Populate view model from entity object here
            });
        return await Task.Run(() => new ObservableCollection<EmployeeViewModel>(query));
    }
}