简体   繁体   English

如何重构此代码以进行LINQ过滤?

[英]How can I refactor this code for LINQ filtering?

Using DataTables (Table plug-in for jQuery) with server side processing I had to create filtering for my data with good performance. 在服务器端处理中使用DataTables(适用于jQuery的Table插件)时,我必须以良好的性能为数据创建过滤。 I did it however in my opinion it's kinda ugly. 我做到了,但是我认为这有点丑陋。 A especially part of ( .Where(...) ) where I have to compare manually each property with search variable. .Where(...) )的一个特别部分,我必须手动比较每个属性和search变量。 Is it possible to make it better? 有可能使它变得更好吗?

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;
    }
}    

You can extract this method: 您可以提取此方法:

public bool SearchForMatching(string source, string serach)
{
    return source.ToLower().Contains(search.ToLower());
} 

It will Simplify your Where clause: 它将简化您的Where子句:

Where(x => SearchForMatching(x.Id, search)
           || SearchForMatching(x.FirstName, search)
           || SearchForMatching(x.LastName, search)
           || SearchForMatching(x.Description, search));

Another option if you don't want to search for every property one by one and you want to check if any of the class's propeties answers the search is to use reflection to iterate over the class's properties and check if there is any one that answers the condition: 如果您不想一个一个地搜索每个属性,并且想要检查该类的任何属性是否满足搜索的另一种选择,则是使用反射来遍历该类的属性,并检查是否有任何一个可以回答该属性。条件:

public bool SearchForMatching(User user, string search)
{
    return user.GetType().GetPropeties().Any(propertyInfo => propertyInfo.GetValue(user).ToString().ToLower().Contains(search.ToLower()));
}

Then use this method in the Where clause: 然后在Where子句中使用此方法:

Where(x => SearchForMatching(x, search));

Or just combine them together: 或者只是将它们组合在一起:

Where(x => x.GetType().GetPropeties().Any(propertyInfo => propertyInfo.GetValue(x).ToString().ToLower().Contains(search.ToLower())); 

Edit 编辑
The two options should work just fine with LINQ to Objects but it will probably not collaborate well with LINQ to Entities because it is not possible to translate neither the first option or the reflection option to SQL using LINQ to Entities. 这两个选项在LINQ to Objects上应该可以很好地工作,但可能无法与LINQ to Entities很好地协作,因为不可能使用LINQ to Entities将第一个选项或反射选项都转换为SQL。

You can load all the data to memeory using db.User.AsEnumerable() and then work with LINQ to Objects with any of these options, but it is less efficient than doing all the filtering in the database like your first query does, I suggest you despite it's readblity to keep your first query. 您可以使用db.User.AsEnumerable()将所有数据加载到内存中,然后使用具有以下任何选项的LINQ to Objects进行操作,但我的效率不如在第一个查询中那样在数据库中进行所有筛选,我建议您尽管可以随时保留第一个查询。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM