【问题标题】:how to build predicate that insensitive text search如何建立不敏感文本搜索的谓词
【发布时间】:2014-07-09 07:13:06
【问题描述】:

我有一个网格视图搜索过滤工具,但有一个缺点。在这里,当用户使用集合搜索字符串时,我必须让它像不敏感的包含一样。

这是我的辅助方法:

 public static IQueryable<T> FilterForColumn<T>(this IQueryable<T> queryable, string colName, string searchText)
    {
        if (colName != null && searchText != null)
        {
            var parameter = Expression.Parameter(typeof(T), "m");
            var propertyExpression = Expression.Property(parameter, colName);
            System.Linq.Expressions.ConstantExpression searchExpression = null;
            System.Reflection.MethodInfo containsMethod = null;
            // this must be of type Expression to accept different type of expressions
            // i.e. BinaryExpression, MethodCallExpression, ...
            System.Linq.Expressions.Expression body = null;
            Expression ex1 = null;
            Expression ex2 = null;
            Expression converted = null;
            switch (colName)
            {
                case "JobID":
                case "status_id":
                    Int32 _int = Convert.ToInt32(searchText);
                    searchExpression = Expression.Constant(_int);
                    containsMethod = typeof(Int32).GetMethod("Equals", new[] { typeof(Int32) });
                    body = Expression.Call(propertyExpression, containsMethod, searchExpression);
                    break;
                case "group_id":
                    Int32? _int1 = Convert.ToInt32(searchText);
                    searchExpression = Expression.Constant(_int1);
                    converted = Expression.Convert(searchExpression, typeof(object));
                    containsMethod = typeof(Int32?).GetMethod("Equals", new[] { typeof(Int32?) });
                    body = Expression.Call(propertyExpression, containsMethod, converted);
                    break;
                case "FileSize":
                case "TotalFileSize":
                    Int64? _int2 = Convert.ToInt64(searchText);
                    searchExpression = Expression.Constant(_int2);
                    converted = Expression.Convert(searchExpression, typeof(object));
                    containsMethod = typeof(Int64?).GetMethod("Equals", new[] { typeof(Int64?) });
                    body = Expression.Call(propertyExpression, containsMethod, converted);
                    break;
                // section for DateTime? properties
                case "PublishDate":
                case "Birth_date":
                case "Anniversary_date":
                case "Profile_Updated_datetime":
                case "CompletedOn":
                    DateTime currentDate = DateTime.ParseExact(searchText, "dd/MM/yyyy", null);
                    DateTime nextDate = currentDate.AddDays(1);
                    ex1 = Expression.GreaterThanOrEqual(propertyExpression, Expression.Constant(currentDate, typeof(DateTime?)));
                    ex2 = Expression.LessThan(propertyExpression, Expression.Constant(nextDate, typeof(DateTime?)));
                    body = Expression.AndAlso(ex1, ex2);
                    break;
                // section for DateTime properties
                case "Created_datetime":
                case "Reminder_Date":
                case "News_date":
                case "thought_date":
                case "SubscriptionDateTime":
                case "Register_datetime":
                case "CreatedOn":
                    DateTime currentDate1 = DateTime.ParseExact(searchText, "dd/MM/yyyy", null);
                    DateTime nextDate1 = currentDate1.AddDays(1);
                    ex1 = Expression.GreaterThanOrEqual(propertyExpression, Expression.Constant(currentDate1));
                    ex2 = Expression.LessThan(propertyExpression, Expression.Constant(nextDate1));
                    body = Expression.AndAlso(ex1, ex2);
                    break;
                default:
                    searchExpression = Expression.Constant(searchText);
                    containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
                    body = Expression.Call(propertyExpression, containsMethod, searchExpression);
                    break;
            }
            var predicate = Expression.Lambda<Func<T, bool>>(body, new[] { parameter });
            return queryable.Where(predicate);
        }
        else
        {
            return queryable;
        }
    }

在默认情况下,我必须将containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) }); 设为不区分大小写。

谁能帮帮我...

更新

我发现这个查询部分有问题:

  post = db.Posts.Where(p => (p.ToUser_id.Equals(user_id) || p.ToUser_id.Equals(null)) && p.User_id != user_id).OrderByDescending(p => p.Sent_Datetime).Select(p => new
                    {
                        Id = p.Id,
                        Title = p.Title,
                        Publisher = db.Users.Where(u => u.Id.Equals(p.User_id)).Select(u => u.First_name + ' ' + u.Last_name).FirstOrDefault(),
                        ToUser = db.Users.Where(u => u.Id.Equals(p.ToUser_id)).Select(u => u.First_name + ' ' + u.Last_name).FirstOrDefault(),
                        PublishDate = p.Sent_Datetime,
                        IsFile = p.IsFileAttached,
                        CategoryName = db.Categories.Where(c => c.Id.Equals(p.Category_id)).Select(c => c.Category_name).FirstOrDefault(),
                        status_name = db.Status.Where(s => s.Id.Equals(p.status_id)).Select(s => s.status_name).FirstOrDefault(),
                        Group_name = db.Groups.Where(g => g.Id.Equals(p.group_id)).Select(g => g.Group_name).FirstOrDefault(),
                        FileSize = p.TotalFileSize
                    }).FilterForColumn(ColumnName, SearchText).ToList();


The translation of String.IndexOf to SQL does not support versions with a StringComparison argument.

【问题讨论】:

  • SQL默认不区分大小写,所以应该没有问题。
  • 我试过了,但这个搜索词仍然区分大小写。
  • 你应该使用SqlMethods.Like而不是Contains
  • 这可以与 .net 4.0 框架一起使用吗
  • 在 .NET 3.5 中引入了 Linq2SQL,是的。

标签: c# .net linq linq-to-sql linq-expressions


【解决方案1】:

如果您将默认大小写更改为使用IndexOf 而不是Contains,它应该可以解决您的问题:

default:
    propertyExpression = Expression.Property(parameter, colName);
    searchExpression = Expression.Constant(searchText);
    containsMethod = typeof(string).GetMethod("IndexOf", new[] { typeof(string), typeof(StringComparison) });
    ConstantExpression compareExpression = Expression.Constant(StringComparison.OrdinalIgnoreCase);
    ex1 = Expression.Call(propertyExpression, containsMethod, searchExpression, compareExpression);
    body = Expression.NotEqual(ex1, Expression.Constant(-1));
    break;

【讨论】:

  • 我发现了这样的错误:String.IndexOf 到 SQL 的翻译不支持带有 StringComparison 参数的版本。
【解决方案2】:

我得到了更准确的答案

当我附加 ToLower() 函数时。

default:
   searchExpression = Expression.Constant(searchText.ToLower());
   containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
   body = Expression.Call(propertyExpression, containsMethod, searchExpression);
   break;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-01
    • 2020-02-06
    • 1970-01-01
    • 1970-01-01
    • 2016-01-30
    相关资源
    最近更新 更多