LIKE operator in LINQ

前端 未结 14 1023
一生所求
一生所求 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:42

    Typically you use String.StartsWith/EndsWith/Contains. For example:

    var portCode = Database.DischargePorts
                           .Where(p => p.PortName.Contains("BALTIMORE"))
                           .Single()
                           .PortCode;
    

    I don't know if there's a way of doing proper regular expressions via LINQ to SQL though. (Note that it really does depend on which provider you're using - it would be fine in LINQ to Objects; it's a matter of whether the provider can convert the call into its native query format, e.g. SQL.)

    EDIT: As BitKFu says, Single should be used when you expect exactly one result - when it's an error for that not to be the case. Options of SingleOrDefault, FirstOrDefault or First should be used depending on exactly what's expected.

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

    Like Extension Linq / SQL

    LikeExtension Class

    Tested in .NET 5

     public static class LikeExtension {
    
        private static string ColumnDataBase<TEntity, TKey>(IModel model, Expression<Func<TEntity, TKey>> predicate) where TEntity : class {
    
            ITable table = model
                .GetRelationalModel()
                .Tables
                .First(f => f
                    .EntityTypeMappings
                    .First()
                    .EntityType == model
                    .FindEntityType(predicate
                        .Parameters
                        .First()
                    .Type
                ));
    
            string column = (predicate.Body as MemberExpression).Member.Name;
            string columnDataBase = table.Columns.First(f => f.PropertyMappings.Count(f2 => f2.Property.Name == column) > 0).Name;
    
            return columnDataBase;
    
        }
    
        public static IQueryable<TEntity> Like<TEntity, TKey>(this DbContext context, Expression<Func<TEntity, TKey>> predicate, string text) where TEntity : class {
    
            string columnDataBase = ColumnDataBase(context.Model, predicate);
            return context.Set<TEntity>().FromSqlRaw(context.Set<TEntity>().ToQueryString() + " WHERE [" + columnDataBase + "] LIKE {0}", text);
    
        }
    
        public static async Task<IEnumerable<TEntity>> LikeAsync<TEntity, TKey>(this DbContext context, Expression<Func<TEntity, TKey>> predicate, string text, CancellationToken cancellationToken) where TEntity : class {
    
            string columnDataBase = ColumnDataBase(context.Model, predicate);
            return await context.Set<TEntity>().FromSqlRaw(context.Set<TEntity>().ToQueryString() + " WHERE [" + columnDataBase + "] LIKE {0}", text).ToListAsync(cancellationToken);
    
        }
    
        public static async Task<IEnumerable<TEntity>> LikeAsync<TEntity, TKey>(this IQueryable<TEntity> query, Expression<Func<TEntity, TKey>> predicate, string text, CancellationToken cancellationToken) where TEntity : class {
    
            DbSet<TEntity> entities = query as DbSet<TEntity>;
            string columnDataBase = ColumnDataBase(entities.EntityType.Model, predicate);
            return await entities.FromSqlRaw(query.ToQueryString() + " WHERE [" + columnDataBase + "] LIKE {0}", text).ToListAsync(cancellationToken);
    
        }
    
        public static IQueryable<TEntity> Like<TEntity, TKey>(this IQueryable<TEntity> query, Expression<Func<TEntity, TKey>> predicate, string text) where TEntity : class {
    
            DbSet<TEntity> entities = query as DbSet<TEntity>;
            string columnDataBase = ColumnDataBase(entities.EntityType.Model, predicate);
            return entities.FromSqlRaw(query.ToQueryString() + " WHERE [" + columnDataBase + "] LIKE {0}", text);
    
        }
    
    }
    

    Repository

        public async Task<IEnumerable<TEntity>> LikeAsync<TKey>(Expression<Func<TEntity, TKey>> predicate, string text, CancellationToken cancellationToken) {
    
            return await context.LikeAsync(predicate, text, cancellationToken);
    
        }
    
        public IQueryable<TEntity> Like<TKey>(Expression<Func<TEntity, TKey>> predicate, string text) {
    
            return context.Like(predicate, text);
    
        }
    

    Use

     IQueryable<CountryEntity> result = countryRepository
         .Like(k => k.Name, "%Bra[sz]il%") /*Use Sync*/
         .Where(w => w.DateRegister < DateTime.Now) /*Example*/
         .Take(10); /*Example*/
    

    Or

     IEnumerable<CountryEntity> result = await countryRepository
         .LikeAsync(k => k.Name, "%Bra[sz]il%", cancellationToken); /*Use Async*/
    

    Or

     IQueryable<CountryEntity> result = context.Countries
         .Like(k => k.Name, "%Bra[sz]il%")
         .Where(w => w.Name != null); /*Example*/
    

    Or

     List<CountryEntity> result2 = await context.Countries
         .Like(k => k.Name, "%Bra[sz]il%")
         .Where(w => w.Name != null) /*Example*/
         .ToListAsync(); /*Use Async*/
    

    Or

     IEnumerable<CountryEntity> result3 = await context.Countries
         .Where(w => w.Name != null)
         .LikeAsync(k => k.Name, "%Bra[sz]il%", cancellationToken); /*Use Async*/
    
    0 讨论(0)
  • 2020-11-27 16:46
      .Where(e => e.Value.StartsWith("BALTIMORE"))
    

    This works like "LIKE" of SQL...

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

    @adobrzyc had this great custom LIKE function - I just wanted to share the IEnumerable version of it.

    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) });
    
        private static 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).Compile();
        }
    
        public static IEnumerable<TSource> Like<TSource, TMember>(this IEnumerable<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:50

    In native LINQ you may use combination of Contains/StartsWith/EndsWith or RegExp.

    In LINQ2SQL use method SqlMethods.Like()

        from i in db.myTable
        where SqlMethods.Like(i.field, "tra%ata")
        select i
    

    add Assembly: System.Data.Linq (in System.Data.Linq.dll) to use this feature.

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

    Ideally you should use StartWith or EndWith.

    Here is an example:

    DataContext  dc = new DCGeneral();
    List<Person> lstPerson= dc.GetTable<Person>().StartWith(c=> c.strNombre).ToList();
    
    return lstPerson;
    
    0 讨论(0)
提交回复
热议问题