使用DataTables(用于jQuery的表插件)和服务器端处理我必须为我的数据创建具有良好性能的过滤。我这样做但在我看来它有点难看。 (.Where(...)
)的一部分,我必须手动将每个属性与search
变量进行比较。有可能让它变得更好吗?
using System.Linq.Dynamic; // because of special .OrderBy
public class SomeRepository
{
public DataTableDTO GetAllFromBase(int start, int length, string sortColumn, string sortColumnDir, string search)
{
var dataFiltered = db.User
.AsNoTracking()
.Select(x => new { x.Id, x.FirstName, x.LastName, x.Description})
.OrderBy(sortColumn + " " + sortColumnDir)
.Where(search.Length > 0, x => x.Id.ToString().Contains(search.ToLower())
|| x.FirstName.ToLower().Contains(search.ToLower())
|| x.LastName.ToLower().Contains(search.ToLower())
|| x.Description.ToLower().Contains(search.ToLower()));
var recordsFiltered = dataFiltered.Count();
var recordsTotal = db.User.Count();
var dataToShow = dataFiltered
.Skip(start)
.Take(length)
.ToList();
var dataForTable = new DataTableDTO
{
Data = dataToShow,
RecordsTotal = recordsTotal,
RecordsFiltered = recordsFiltered
};
return dataForTable;
}
}
public static class LinqExtensions
{
public static IQueryable<T> Where<T>(this IQueryable<T> query, bool condition, Expression<Func<T, bool>> whereClause)
{
if (condition)
{
return query.Where(whereClause);
}
return query;
}
}
答案 0 :(得分:3)
您可以提取此方法:
public bool SearchForMatching(string source, string serach)
{
return source.ToLower().Contains(search.ToLower());
}
它将简化你的Where子句:
Where(x => SearchForMatching(x.Id, search)
|| SearchForMatching(x.FirstName, search)
|| SearchForMatching(x.LastName, search)
|| SearchForMatching(x.Description, search));
另一种选择,如果您不想逐个搜索每个属性,并且想要检查是否有任何类别的问题回答了搜索,那就是使用反射来迭代课程&#39 ; s属性并检查是否有任何一个符合条件:
public bool SearchForMatching(User user, string search)
{
return user.GetType().GetPropeties().Any(propertyInfo => propertyInfo.GetValue(user).ToString().ToLower().Contains(search.ToLower()));
}
然后在Where子句中使用此方法:
Where(x => SearchForMatching(x, search));
或者只是将它们组合在一起:
Where(x => x.GetType().GetPropeties().Any(propertyInfo => propertyInfo.GetValue(x).ToString().ToLower().Contains(search.ToLower()));
修改强>
这两个选项应该可以正常使用LINQ to Objects但它可能无法与LINQ to Entities很好地协作,因为不可能使用LINQ to Entities将第一个选项或反射选项转换为SQL。 />
您可以使用db.User.AsEnumerable()将所有数据加载到内存中,然后使用任何这些选项使用LINQ to Objects,但它比在第一个查询中执行数据库中的所有过滤效率低,我建议尽管它具有可读性以保持您的第一个查询。