LIKE operator in LINQ

前端 未结 14 1045
一生所求
一生所求 2020-11-27 16:29

Is there any way to compare strings in a C# LINQ expression similar to SQL\'s LIKE operator?

Suppose I have a string list. On this list I want to search

相关标签:
14条回答
  • 2020-11-27 16:50
    List<Categories> categoriess;
            private void Buscar()
            {
                try
                {
                    categoriess = Contexto.Categories.ToList();
                    categoriess = categoriess.Where(n => n.CategoryID >= Convert.ToInt32(txtCatID.Text) && n.CategoryID <= Convert.ToInt32(txtCatID1.Text) && (n.CategoryName.Contains(txtCatName.Text)) ).ToList();
    
    0 讨论(0)
  • 2020-11-27 16:52

    A simple as this

    string[] users = new string[] {"Paul","Steve","Annick","Yannick"};    
    var result = from u in users where u.Contains("nn") select u;
    

    Result -> Annick,Yannick

    0 讨论(0)
  • 2020-11-27 16:56

    Well... sometimes it may be uncomfortable to use Contains, StartsWith or EndsWith especially when searching value determine LIKE statment e.g. passed 'value%' require from developer to use StartsWith function in expression. So I decided to write extension for IQueryable objects.

    Usage

    // numbers: 11-000-00, 00-111-00, 00-000-11
    
    var data1 = parts.Like(p => p.Number, "%11%");
    // result: 11-000-00, 00-111-00, 00-000-11
    
    var data2 = parts.Like(p => p.Number, "11%");
    // result: 11-000-00
    
    var data3 = parts.Like(p => p.Number, "%11");
    // result: 00-000-11
    

    Code

    public static class LinqEx
    {
        private static readonly MethodInfo ContainsMethod = typeof(string).GetMethod("Contains");
        private static readonly MethodInfo StartsWithMethod = typeof(string).GetMethod("StartsWith", new[] { typeof(string) });
        private static readonly MethodInfo EndsWithMethod = typeof(string).GetMethod("EndsWith", new[] { typeof(string) });
    
        public static Expression<Func<TSource, bool>> LikeExpression<TSource, TMember>(Expression<Func<TSource, TMember>> property, string value)
        {
            var param = Expression.Parameter(typeof(TSource), "t");
            var propertyInfo = GetPropertyInfo(property);
            var member = Expression.Property(param, propertyInfo.Name);
    
            var startWith = value.StartsWith("%");
            var endsWith = value.EndsWith("%");
    
            if (startWith)
                value = value.Remove(0, 1);
    
            if (endsWith)
                value = value.Remove(value.Length - 1, 1);
    
            var constant = Expression.Constant(value);
            Expression exp;
    
            if (endsWith && startWith)
            {
                exp = Expression.Call(member, ContainsMethod, constant);
            }
            else if (startWith) 
            {
                exp = Expression.Call(member, EndsWithMethod, constant);
            }
            else if (endsWith)
            {
                exp = Expression.Call(member, StartsWithMethod, constant);
            }
            else
            {
                exp = Expression.Equal(member, constant);
            }
    
            return Expression.Lambda<Func<TSource, bool>>(exp, param);
        }
    
        public static IQueryable<TSource> Like<TSource, TMember>(this IQueryable<TSource> source, Expression<Func<TSource, TMember>> parameter, string value)
        {
            return source.Where(LikeExpression(parameter, value));
        }
    
        private static PropertyInfo GetPropertyInfo(Expression expression)
        {
            var lambda = expression as LambdaExpression;
            if (lambda == null)
                throw new ArgumentNullException("expression");
    
            MemberExpression memberExpr = null;
    
            switch (lambda.Body.NodeType)
            {
                case ExpressionType.Convert:
                    memberExpr = ((UnaryExpression)lambda.Body).Operand as MemberExpression;
                    break;
                case ExpressionType.MemberAccess:
                    memberExpr = lambda.Body as MemberExpression;
                    break;
            }
    
            if (memberExpr == null)
                throw new InvalidOperationException("Specified expression is invalid. Unable to determine property info from expression.");
    
    
            var output = memberExpr.Member as PropertyInfo;
    
            if (output == null)
                throw new InvalidOperationException("Specified expression is invalid. Unable to determine property info from expression.");
    
            return output;
        }
    }
    
    0 讨论(0)
  • 2020-11-27 16:56

    As Jon Skeet and Marc Gravell already mentioned, you can simple take a contains condition. But in case of your like query, it's very dangerous to take a Single() statement, because that implies that you only find 1 result. In case of more results, you'll receive a nice exception :)

    So I would prefer using FirstOrDefault() instead of Single():

    var first = Database.DischargePorts.FirstOrDefault(p => p.PortName.Contains("BALTIMORE"));
    var portcode = first != null ? first.PortCode : string.Empty;
    
    0 讨论(0)
  • 2020-11-27 17:00

    You can call the single method with a predicate:

    var portCode = Database.DischargePorts
                       .Single(p => p.PortName.Contains("BALTIMORE"))
                       .PortCode;
    
    0 讨论(0)
  • 2020-11-27 17:02
       public static class StringEx
        {
            public static bool Contains(this String str, string[] Arr, StringComparison comp)
            {
                if (Arr != null)
                {
                    foreach (string s in Arr)
                    {
                        if (str.IndexOf(s, comp)>=0)
                        { return true; }
                    }
                }
    
                return false;
            }
    
            public static bool Contains(this String str,string[] Arr)
            {
                if (Arr != null)
                {
                    foreach (string s in Arr)
                    {
                        if (str.Contains(s))
                        { return true; }
                    }
                }
    
                return false;
            }
        }
    
    
    var portCode = Database.DischargePorts
                       .Single(p => p.PortName.Contains( new string[] {"BALTIMORE"},  StringComparison.CurrentCultureIgnoreCase) ))
                       .PortCode;
    
    0 讨论(0)
提交回复
热议问题